如果我提出的任何概念(例如 lambda 函数)不清楚,请在 LYAH 中阅读它们并在ghci
. 然后再次回到这个回复,一切都应该清楚一点!
如果您来自其他编程语言,可能会令人困惑的一件事是,在 Haskell 中,您可以使用诸如
runState
并添加一个参数
runState m
它仍然是一个有效的功能。如果您随后添加第二个参数,如下所示:
runState m st
它最终会计算一个值。这意味着 ifrunState
是两个参数的函数,thenrunState m
是一个参数的函数,可以像任何其他一个参数的函数一样对待。
您的示例中的重要一点是
\st -> let (a, s) = runState m st in (f a, s)
可以变成
(\(a,s) -> (f a,s)) . runState m
使用运算符进行函数组合,(.)
.
理解这如何可能的第一步是认识到let…in
可以用 lambda 形式重写表达式。这意味着
let y = f x in expr
可以写成
(\y -> expr) (f x)
这两行都会将名称绑定y
到 的值f x
,这实际上就是我们需要的let…in
表达式。
如果你将这些知识应用到
\st -> let (a, s) = runState m st in (f a, s)
你会看到它可以重写为
\st -> (\(a, s) -> (f a, s)) (runState m st)
我们已经成功了一半!
函数组合的定义是这样的:
f . g = \x -> f (g x)
这意味着任何时候你有一些看起来\x -> f (g x)
你可以用 just 替换它的东西f . g
。
好吧,在这种情况下,我们确实有一些看起来像这样的东西!如果我们这么说
f = \(a, s) -> (f a, s)
g = runState m
x = st
我们看到
\st -> (\(a, s) -> (f a, s)) (runState m st)
\x -> f (g x)
只不过是等待发生的功能组合。所以我们可以把它变成
f . g
根据我们对f
和的定义g
,
f . g
(\(a, s) -> (f a, s)) . (runState m)
并且您可以将括号放在runState m
.