haskell - 为什么>>=比<=<更常被讨论?

标签 haskell

假设我们有 g :: a -> b ,和f :: b -> c 。我们可以这样写:

  1. f . g :: a -> c .

如果我们的函数返回一元值(即上下文中的值),例如 g1 :: (Monad m) => a -> m bf1 :: (Monad m) => b -> m c 。我们可以这样写:

  1. f1 <=< g1 :: (Monad m) => a -> m c .
  2. return x >>= g1 >>= f1 ,其中x :: a ,以获得一个值。甚至是 lambda \x -> return x >>= g1 >>= f1 .

看来<=<. 更平行在语法方面。 <=<更容易理解Monad只是关于保留上下文的函数组合。为什么是>>=<=<更常被谈论?

最佳答案

<=<是解释 monad laws 的好方法。 :

 f <=< return = f -- right identity
 return <=< g = g -- left identity
 f <=< (g <=< h) = (f <=< g) <=< h -- associativity

它对于演示 Kleisli 箭头的类别非常有用:

 newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }
 instance Monad m => Category (Kleisli m) where
   Kleisli f . Kleisli g = Kleisli (f <=< g)
   id = Kleisli return

您会看到它出现在无积分程序中。就我个人而言,我也很喜欢它的同行=<< .

虽然它使谈论单子(monad)定律和组合变得更容易,但我认为仍然有一些强有力的说教原因 >>=在 monad 教程和 Haskell 介绍中是首选。

第一个原因是<=<的强项是无点代码,对于来自 C 语法系列语言(C、C++、Java、Python 等)的人来说,大多数情况下,无点代码一开始更难理解。

如果“point-free”对您来说是一个陌生的形容词,那么这里有同一函数的三个实现:

f a b = a + b * 2
f a = (a +) . (* 2)
f = flip (.) (*2) . (+)

它们都运行相同的计算,但最后一个采用所谓的“无点”风格,其中左侧的变量已通过 eta conversion 删除。 。

这个例子很像一个稻草人,但无点风格很诱人,很容易导致初学者很难理解的代码。

另一个原因是初学者几乎都会问的问题之一是 “如何打开 IO String 以获得 String ?”当第一次遇到 haskell 的IO单子(monad)。答案当然是,“你不这样做,你把其余的链起来 >>= 的计算", >>= 更容易解释这种关系 之间

putStrLn "Your first name: " >>= \_ ->
getLine >>= \first ->
putStrLn "Your last name: " >>= \_ ->
getLine >>= \last ->
putStrLn ("Hello " ++ first ++ " " ++ last)

do
  putStrLn "Your first name: "
  first <- getLine
  putStrLn "Your last name: "
  last <- getLine
  putStrLn ("Hello " ++ first ++ " " ++ last)

当然,最后一个原因是 >>=位于 Monad 的定义中, 和 <=<不是,这就是语言的定义方式。人们是 当以下情况时,更有可能谈论类型类成员而不是任意函数 向其他人传授有关类型类的知识,尤其是当老师 对于该主题本身来说相对较新(正如许多 monad 教程作者一样)。

关于haskell - 为什么>>=比<=<更常被讨论?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45513040/

相关文章:

haskell - 这种特殊的仿函数结构叫什么?

haskell - Haddock 丢失部分文档?

haskell - Hackage 使用哪种 Markdown 方言来呈现 README?

haskell - 融合遍历

algorithm - 是否有任何允许并行加法的自然数代数表示?

haskell - Haskell 中附加词的用例

ios - iOS 5 下的 Haskell : suppressing output

Haskell 数据类型语法与操作,第二部分

haskell - Hackage 有 API 吗?

haskell - 如何解释编译器消息 'Couldn' t 匹配类型 : [b0] with: [a2] -> t :'?