将非monadic函数绑定到monad

时间:2014-08-13 09:45:49

标签: haskell monads function-composition

也许这是一个经常被问到的问题,但我没有找到答案。

monad的绑定定义如下:

(>>=)  :: m a -> (a -> m b) -> m b

目前我正在这样做:

foo :: Int
foo = sum $ ((*11) . (+2)) `map` [1..4]

我想实现这样的语法,因为我认为它更具可读性:

[1..4] >>= (+2) >>= (*11) >>= sum

我不知道正确的运算符而不是>>=

此外:foo是198。

1 个答案:

答案 0 :(得分:9)

在这种情况下最可读的当然是

   sum [ (x+2)*11 | x<-[1..4] ]

但是如果你想要它没有点,没有额外的parens,只需用infix fmap operator重写原始行:

   sum $ (*11) . (+2) <$> [1..4]

如果您只想转换订单,可以将.替换为等效的翻转运算符from Control.Category,将$替换为its flipped version e.g. from lens

   [1..4] & fmap((+2)>>>(*11)) & sum

然后再说一次,如果你追求数学优雅并希望它像一个单子一样工作,那么这是不可能的,因为这里没有任何monadic。然而,你可以争辩sum是一个Cokleisli箭头(不可定义,在Haskell 98中)Monoid - 有限列表comonad。我们可以通过NonEmpty comonad来近似并写下

    extract $ fromList [1..4] =>> (extract>>>(+2)>>>(*11)) =>> sum.toList

但这太荒谬了。