haskell - 减少 Haskell 表达式

标签 haskell functional-programming monads reduction

您好,我是 Haskell 新手,主要阅读 LYAHHutton . 最近我遇到了这个片段,其中 Functor 实例 一个状态单子(monad),表示为:

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

谁能解释这种减少背后的工作流程?

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

最佳答案

如果我提出的任何概念(例如 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 绑定(bind)到 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 周围。

关于haskell - 减少 Haskell 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19766772/

相关文章:

haskell - 暂停单子(monad)

haskell - 为什么这个 Functor 实例不正确?

java - 函数接口(interface)的回调接口(interface)

Clojure 序列长度

types - 关于置换的表示

c# - 是否已经内置了像这样的功能性 C#/.NET 结构? g(h()), 或

haskell - 为什么我不能使 String 成为类型类的实例?

haskell - 记录语法中具有大量构造函数的代数数据类型的替代方案

haskell - Haskell 类定义中的隐式类型参数?

haskell - 缩进操作符