【问题标题】:Maybe coalescing operator也许合并运算符
【发布时间】:2018-05-02 11:42:33
【问题描述】:

我想知道如何定义一个运算符/如果 Haskell 中已经存在一个运算符,让我们选择第一个不是 NothingMaybe 类型,如果它们都没有,它会返回一些默认值。基本上是这样的:

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

其中(??) 是运算符,a, b, c 都是Maybe 类型。如果所有a, b, c 都是Nothing,我希望这段代码返回Just1 的第一个值。

我基本上希望复制与您在 C# 或其他语言中找到的空合并运算符相同的功能。

这个问题展示了如何在 F# (Null Coalescing Operator in F#?),它很 hacky。有没有办法在 Haskell 中干净利落地做到这一点,如果没有,你最接近它的方法是什么?

【问题讨论】:

  • Hoogle 是寻找这类东西的好工具。

标签: haskell null maybe null-coalescing-operator


【解决方案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

【讨论】:

  • 这行得通,但我认为你是对的,我应该清楚我希望它以我上面指定的方式专门完成。我将对其进行编辑并添加一个我在 F# 中看到的示例。
  • @m0meni 我不会对 F# 进行编程,对不起。但我可以向您展示如何使用 haskell 中的运算符(但有两个运算符)。
【解决方案2】:

仅出于一些练习目的,这项工作也可以通过 Monoid 类类型 First 表示,这是一个 Maybe 幺半群,返回最左边的 non-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

【讨论】:

    【解决方案3】:

    Haskeller's 通常会使用 (&lt;|&gt;) :: Maybe a -&gt; Maybe a -&gt; 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
    

    【讨论】:

    • 你的答案更好。
    • 如果你有一个方便的instance Num a =&gt; Num (Maybe a),你可以使用1&lt;|&gt;
    • 我们还可以使用 asum from Data.Foldable 来组合使用 &lt;|&gt; 的可能列表。
    猜你喜欢
    • 2013-06-11
    • 2012-09-19
    • 2010-09-15
    • 2013-09-13
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    • 2011-02-13
    • 1970-01-01
    相关资源
    最近更新 更多