首页 文章

也许合并运算符

提问于
浏览
3

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

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

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

我'm basically looking to replicate the same functionality as the null coalescing operator you' d找到 C# 或其他语言 .

这个问题显示了如何在F#(Null Coalescing Operator in F#?)中完成它,并且's quite hacky. Is there a way to do it cleanly in Haskell, and if not, what'是最接近它的?

3 回答

  • 3

    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
    
  • 12

    你介意用不同的方式写吗?

    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
    
  • 1

    仅仅为了一些练习目的,这个作业也可以用 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
    

相关问题