也许合并运算符
Maybe coalescing operator
我想知道如何定义运算符/如果运算符已经存在于 Haskell 中,让我们选择第一个 Maybe
类型而不是 Nothing
,如果全部都没有,它 return 是一些默认值。基本上是这样的:
let x = a ?? b ?? c ?? 1
其中(??)
是运算符,a, b, c
都是Maybe
类型。我希望这段代码 return 第一个值是 Just
或 1
如果所有 a, b, c
都是 Nothing
.
我基本上是想复制与您在 C#
或其他语言中找到的空合并运算符相同的功能。
这个问题展示了如何做
F# (Null Coalescing Operator in F#?),它非常老套。有没有办法在 Haskell 中干净利落地做到这一点,如果没有,您最接近它的方法是什么?
你介意用不同的方式写吗?
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
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
出于一些练习目的,这项工作也可以用 Monoid
class 类型 First
表示,它是一个 Maybe
幺半群,返回最左边的非 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
我想知道如何定义运算符/如果运算符已经存在于 Haskell 中,让我们选择第一个 Maybe
类型而不是 Nothing
,如果全部都没有,它 return 是一些默认值。基本上是这样的:
let x = a ?? b ?? c ?? 1
其中(??)
是运算符,a, b, c
都是Maybe
类型。我希望这段代码 return 第一个值是 Just
或 1
如果所有 a, b, c
都是 Nothing
.
我基本上是想复制与您在 C#
或其他语言中找到的空合并运算符相同的功能。
这个问题展示了如何做 F# (Null Coalescing Operator in F#?),它非常老套。有没有办法在 Haskell 中干净利落地做到这一点,如果没有,您最接近它的方法是什么?
你介意用不同的方式写吗?
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
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
出于一些练习目的,这项工作也可以用 Monoid
class 类型 First
表示,它是一个 Maybe
幺半群,返回最左边的非 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