簡體   English   中英

如何使用may monoid並將值與自定義操作相結合?

[英]How to use the maybe monoid and combine values with a custom operation, easily?

基本上,我想要做的是手工定義

maybeCombine :: (a->a->a) -> Maybe a -> Maybe a -> Maybe a
maybeCombine _ Nothing Nothing = Nothing
maybeCombine _ (Just a) Nothing = Just a
maybeCombine _ Nothing (Just a) = Just a
maybeCombine f (Just a) (Just a') = Just $ f a a'

在需要的時候在本地定義它並不是什么大不了的事,但仍然是笨拙的,並且如此基本和一般似乎應該有一個標准的實現,但我似乎找不到一個。

也許我只是忽略了一些東西。 我想要的似乎與monad的行為完全無關,所以我認為我在Monad / Arrow抽屜里找不到任何東西; 但它確實類似於Monoid實例

Prelude Data.Monoid>只是“a”<>沒什么
只是“一個”
Prelude Data.Monoid>只是“a”<>只是“b”
只是“ab”
...

...然而,它需要a幺半群本身,即它基本上具有a->a->a “內置”。 MonadPlus實例的行為也很像我想要的,但它只是拋棄了其中一個值而不是允許我提供組合函數

Prelude Data.Monoid Control.Monad> Just 4`mplus`沒什么
只是4
Prelude Data.Monoid Control.Monad>沒什么`mplus`只是4
只是4
Prelude Data.Monoid Control.Monad> Just 4`mplus`只需5
只是4

什么是規范解決方案? 局部模式匹配? 使用例如Data.Maybe組合器的東西? 定義一個自定義的monoid進行組合?

你可以隨時使用

f <$> m <*> n <|> m <|> n

但遺憾的是,這在任何地方都沒有規范的實施。

您可以使用reflection(a -> a -> a) “烘焙”作為SemigroupOption一起使用,它由semigroups提供,作為Maybe的改進版本,具有Monoid的“正確”實例Semigroup 盡管如此,這對於這個問題來說太過沉重。 =)

也許這應該只是作為Data.Maybe的組合子Data.Maybe

當你注意到你是正確的金錢f就像是一個Monoid上的基本操作a類型。 更具體地說,這里發生的是你通過連接零( mempty ), NothingSemigroup提升為Monoid

這正是你在Haddocks中為Maybe Monoid看到的。

根據http://en.wikipedia.org/wiki/Monoid將一個半群提升為Maybe形成一個Monoid:“任何半群S可以簡單地通過連接一個不在S中的元素e並定義e e = e而變成一個monoid。所有s∈S的e s = s = s * e“ 由於沒有提供mappend的“Semigroup”類型類,我們使用Monoid代替。

或者,如果你喜歡semigroups包,那么Option就有這種行為,適當地推廣使用底層Semigroup


因此,這表明最明確的方法是在底層類型a上定義MonoidSemigroup實例。 將一些組合器f與該類型相關聯是一種干凈的方法。

如果你不控制那種類型,不想要孤立實例,並認為newtype包裝器是丑陋的怎么辦? 通常你會失去運氣,但這是一個使用全黑魔法的地方,有效的GHC reflection包就派上用場了。 本文中有 完整的解釋Ausin Seipp的FP完整教程包含一些示例代碼,允許您將任意半群產品“注入”到沒有(盡可能多)類型定義噪聲的類型中,代價是更加可怕的簽名。

然而,這可能比它的價值明顯更多。

import Data.Monoid
maybeCombine :: (a->a->a) -> Maybe a -> Maybe a -> Maybe a
maybeCombine f mx my = let combine = mx >>= (\x -> my >>= (\y -> Just (f x y)))
                       in getFirst $ First combine `mappend` First mx `mappend` First` my

在GHCi,這給了我

*Main> maybeCombine (+) Nothing Nothing
Nothing
*Main> maybeCombine (+) (Just 3) Nothing
Just 3
*Main> maybeCombine (+) (Just 3) (Just 5)
Just 8

如果將Last combine放在mappend序列的末尾,也可以使用getLast

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM