减少Haskell表达式

时间:2013-11-04 11:28:14

标签: haskell functional-programming monads reduction

您好我是Haskell的新手,主要是从LYAHHutton阅读。 最近我遇到了这个Functor实例的片段 国家单子,表示为:

instance Functor (State st) where
    fmap f m = State $ \st -> let (a, s) = runState m st in (f a, s)

这可以简化为:

instance Functor (State st) where 
    fmap f m = State $ (\(a,s) -> (f a,s)) . runState m

有人能解释这种减少背后的工作流程吗?

关于如何学习这种减少技术,还有哪些好的资源/建议?

1 个答案:

答案 0 :(得分:9)

如果我提出的任何概念(例如lambda函数)都不清楚,请在LYAH中阅读它们并在ghci中与它们一起玩一下。然后再回到这个回复,一切都应该清理一下!

如果你来自其他编程语言,可能会让人感到困惑的一件事是,在Haskell中,你可以使用诸如

这样的函数
runState

并添加一个参数

runState m

它仍然是一个有效的功能。如果你然后添加第二个参数,如下所示:

runState m st

它最终将计算一个值。这意味着如果runState是两个参数的函数,则runState 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)内容,就可以只用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

,我们对fg的定义,

f                     . g
(\(a, s) -> (f a, s)) . (runState m)

并且您可以将括号放在runState m附近。