也许合并运营商
我想知道如何才能定义一个运算符/如果Haskell中已经存在一个运算符,它允许选择第一个不是Nothing
Maybe
类型,如果它们全都是Nothing
,它将返回一些默认值。 基本上是这样的:
let x = a ?? b ?? c ?? 1
其中(??)
是运算符, a, b, c
都是Maybe
类型。 我希望这段代码返回的第一个值是Just
或1
如果a, b, c
都是Nothing
。
我基本上希望复制与您在C#
或其他语言中找到的空合并运算符相同的功能。
这个问题展示了如何在F#中完成它(F#中的空合并运算符?),而且这很麻烦。 有没有办法在Haskell中干净地做到这一点,如果没有,那么最接近它的是什么?
Haskeller通常会使用(<|>) :: Maybe a -> Maybe a -> Maybe a
这样的事情。 假设a, b, c :: Maybe Int
,你有x :: Maybe Int
let x = a <|> b <|> c <|> Just 1
当然,这不是你要求的。 如果你想,你可以定义它!
-- 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
然后,你就会得到你期望的行为。 假设a, b, c :: Maybe Int
,你有x :: Int
:
let x = a ?? b ?? c ?? 1
你介意以不同的方式写作吗?
safeHead [] d = d
safeHead (h:_) _ = h
然后
let x = safeHead (catMaybes [a, b, c]) 1
应该做你想做的。
如果你想这样做,这是可行的,但需要两名操作员。
a@(Just _) ?? _ = a
_ ?? b = b
(Just e) ?: _ = e
_ ?: d = d
定义你需要的两个操作符,它们的工作原理是:
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/57967.html