简体   繁体   English

理解一元函数组合

[英]Understanding monadic function composition

I am learning about monads from the book 'Learn You a Haskell for Great Good!'我正在从“Learn You a Haskell for Great Good!”一书中学习 monads。 by Miran Lipovaca.通过米兰利波瓦卡。 I am trying to understand the associativity law for monads.我试图理解 monad 的结合律。 Essentially, the law states that when you have a chain of monadic function applications with >>= , it shouldn't matter how they're nested.本质上,法律规定,当您拥有一串带有>>=的单子函数应用程序时,它们的嵌套方式无关紧要。

The following code enables one to pass the result of a function of type a -> mb to a function of type b -> mc :以下代码可以将a -> mb类型的函数的结果传递给b -> mc类型的函数:

(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> (a -> m c)
f <=< g = (\x -> g x >>= f)

However, for the example below:但是,对于下面的示例:

ghci> let f x = [x, -x]
ghci> let g x = [x*3, x*2]
ghci> let h = f <=< g
ghci> h 3
[9, -9, 6, -6]

Are fx and gx both functions? fxgx都是函数吗? It seems to be that they are lists with different values of x and not functions.似乎它们是具有不同 x 值而不是函数的列表。 How does the line let h = f <=< g work in the above code?在上面的代码中,这行let h = f <=< g工作的? f and g have to be functions since they are used with <=< but I am not sure what they are. fg必须是函数,因为它们与<=<一起使用,但我不确定它们是什么。

f x = [x, -x]

This is ordinary function definition syntax.这是普通的函数定义语法。 We are defining a new function f , by writing down what it would produce when applied to a hypothetical value x .我们正在定义一个新函数f ,写下它应用于假设值x时会产生什么。

let (whether as a statement or a let ... in ... expression) just introduces a block where you can make definitions, much like where . let (无论是作为语句还是let ... in ...表达式)只是引入了一个可以进行定义的块,就像where一样。 The definitions themselves use the same syntax as global ones do.定义本身使用与全局定义相同的语法。

If you know how to define functions by writing eg plusOne n = n + 1 in a file, then this syntax is exactly the same (if you don't know how to do that, then I'd suggest reading through some introductory tutorials on fundamental Haskell syntax before you try to understand monadic function composition).如果您知道如何通过在文件中编写例如plusOne n = n + 1来定义函数,那么此语法是完全相同的(如果您不知道该怎么做,那么我建议您阅读一些介绍性教程在尝试理解 monadic 函数组合之前,请先了解基本的 Haskell 语法)。

So after those definitions f and g are functions.所以在这些定义之后fg是函数。 fx and gx don't really make sense, since you don't have an x in scope to apply them to. fxgx没有真正意义,因为您没有将它们应用到的x范围。

If you did have such a value in scope, then fx would be an expression that evaluates to a list, which involves calling the function f .如果您在范围内确实有这样的值,那么fx将是一个计算结果为列表的表达式,其中涉及调用函数f It still wouldn't be true to say that fx or gx are functions.fxgx是函数仍然是不正确的。

So now it should be clear that let h = f <=< g is defining a new value h by applying the <=< operator to f and g .所以现在应该清楚let h = f <=< g通过将<=<运算符应用于fg来定义一个新值h

Nothing's better for gaining a feeling of understanding, like working through the definitions by hand on a sheet of paper.没有什么比在一张纸上手工完成定义更能获得理解的感觉了。

fx = [x, -x] can also be written f = (\\ x -> [x, -x]) . fx = [x, -x]也可以写成f = (\\ x -> [x, -x]) Thus因此

  h 3 
= {- by def of h -}
  (f <=< g) 3 
= {- by def of (<=<) -}
  (\x -> g                   x >>= f               ) 3
= {- by defs of f and g -}
  (\x -> (\ x -> [x*3, x*2]) x >>= (\ x -> [x, -x])) 3
= {- by substitution -}
         (\ x -> [x*3, x*2]) 3 >>= (\ x -> [x, -x])
= {- by substitution -}
                 [3*3, 
                  3*2]         >>= (\ x -> [x, -x])
= {- by definition of (>>=) for [] -}
  concat [       (3*3)         &   (\ x -> [x, -x])  -- x & f == f x
         ,       (3*2)         &   (\ x -> [x, -x]) 
         ]
= {- by definition of concat -}
                 (3*3)         &   (\ x -> [x, -x])
         ++      (3*2)         &   (\ x -> [x, -x]) 
= 
  [9, -9, 6, -6]

( edit ) For a picture, and some more discussion of these Kleisli arrows and their composability, see this older answer of mine . 编辑)有关图片以及对这些Kleisli 箭头及其可组合性的更多讨论,请参阅我的这个较旧的答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM