拥有 powershell 脚本编写的背景,我首先认为以管道的方式思考函数组合是很自然的。这意味着组合的语法应该是 fun1 | fun2 | fun3
以伪代码的方式。 (其中 fun[i]
是按顺序应用的 i
个函数)。这种函数顺序也是您在 haskell monadic 绑定(bind)中找到的。 fun1 >>= fun2 >>= fun3
.
但在haskell中的其他场合,函数的顺序更加数学化,例如fun3 . fun2 . fun1
,或在函数设置 fmap fun3 . fmap fun2 . fmap fun1
中.
我非常清楚这两个示例中的函数具有不同的签名,但令我困惑的是结构是相反的。我的解决方法是有时定义一个函数 mmap = flip (>>=)
这样我就可以写mmap fun3 . mmap fun2 . mmap fun1
.
所以这个问题:
- 有没有
mmap
已经定义了?这叫什么? - 为什么如果将 bind 定义为一个带有参数的运算符,其参数的顺序感觉是倒退的?
最佳答案
Is there a
mmap
already defined? What is is called?
Hoogle是你的 friend 。 (>>=)
的类型签名是:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
因此,您正在寻找具有类型签名的函数:
flip (>>=) :: Monad m => (a -> m b) -> m a -> m b
这实际上是 =<<
功能。因此,您可以写 fun3 =<< fun2 =<< fun1
.
Why is bind defined as an operator with arguments in an order that feels backwards?
这是因为一元代码看起来很像命令式代码。例如,请考虑以下情况:
permute2 :: [a] -> [[a]]
permute2 xs = do
x <- xs
xs <- map return xs
return (x:xs)
没有 do
的语法糖它会写成:
permute2 :: [a] -> [[a]]
permute2 xs =
xs >>= \x ->
map return xs >>= \xs ->
return (x:xs)
看到相似之处了吗?如果我们使用=<<
相反,它看起来像:
permute2 :: [a] -> [[a]]
permute2 xs = (\x -> (\xs -> return (x:xs)) =<< map return xs) =<< xs
可读性不是很好吗?
关于haskell - fmap 的单子(monad) "versions"的名称是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45775730/