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?
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
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
仅仅为了一些练习的目的,这个工作也可以由Monoid
类类型表示, First
一个是Maybe
monoid,返回最左边的非Nothing值。
import Data.Monoid
import Data.Maybe (fromJust)
infixr 3 ??
(??) :: Maybe a -> a -> a
x ?? y = fromJust . getFirst $ First x <> First (Just y)
*Main> Nothing ?? Nothing ?? 1
1
*Main> Nothing ?? Just 3 ?? 1
3
*Main> Just 7 ?? Just 3 ?? 1
7
链接地址: http://www.djcxy.com/p/57968.html
上一篇: 使用空合并操作符的独特方法
下一篇: 也许合并运营商