Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maybe coalescing operator

I'm wondering how I could go about defining an operator / if an operator already exists in Haskell that lets pick the first Maybe type that isn't Nothing, and if all if them are nothing, it returns some default. Basically something like this:

let x = a ?? b ?? c ?? 1

where (??) is the operator and a, b, c are all Maybe types. I'd expect this code to return the first value that is Just or 1 if all of a, b, c are Nothing.

I'm basically looking to replicate the same functionality as the null coalescing operator you'd find in C# or other languages.

This question shows how to do it in F# (Null Coalescing Operator in F#?), and it's quite hacky. Is there a way to do it cleanly in Haskell, and if not, what's the closest you can get to it?

like image 739
m0meni Avatar asked Dec 03 '22 21:12

m0meni


2 Answers

Haskeller's would generally use (<|>) :: Maybe a -> Maybe a -> Maybe a for this sort of thing. Assuming a, b, c :: Maybe Int, you have x :: Maybe Int

let x = a <|> b <|> c <|> Just 1

Of course, that isn't really what you asked for. If you want, you could define it though!

-- You expect `a ?? b ?? c ?? 1` to parse as `a ?? (b ?? (c ?? 1))`
infixr 3 ??

-- (Someone is going to point out that `(??) = flip fromMaybe`, so I am first)
(??) :: Maybe a -> a -> a
Just x ?? _ = x
Nothing ?? y = y

Then, you get precisely the behaviour you expect. Assuming a, b, c :: Maybe Int, you have x :: Int:

let x = a ?? b ?? c ?? 1
like image 181
Alec Avatar answered Dec 30 '22 05:12

Alec


Do you mind writing it differently?

safeHead [] d = d
safeHead (h:_) _ = h

then

let x = safeHead (catMaybes [a, b, c]) 1

shall do what you want.

If you want to do it in that way, it's doable, but two operators are required.

a@(Just _) ?? _ = a
_ ?? b = b

(Just e) ?: _ = e
_ ?: d = d

defines the two operators you need, and they work:

Prelude> let a = Nothing
Prelude> let b = Nothing
Prelude> let c = Just 3
Prelude> a ?? b ?? c ?: 10
3
Prelude> a ?? b ?? Nothing ?: 10
10
like image 27
Jason Hu Avatar answered Dec 30 '22 03:12

Jason Hu