Pau*_*l K 3 monads haskell functional-programming reduction
嗨,我是Haskell的新手,主要是从LYAH和Hutton读书.最近我遇到了这个状态monad的Functor实例的片段,表示为:
instance Functor (State st) where
fmap f m = State $ \st -> let (a, s) = runState m st in (f a, s)
Run Code Online (Sandbox Code Playgroud)
这可以简化为:
instance Functor (State st) where
fmap f m = State $ (\(a,s) -> (f a,s)) . runState m
Run Code Online (Sandbox Code Playgroud)
谁能解释这种减少背后的工作流程?
关于如何学习这种减少技术,还有哪些好的资源/建议?
如果我提出的任何概念(例如lambda函数)都不清楚,请在LYAH中阅读它们并与它们一起玩ghci.然后再回到这个回复,一切都应该清理一下!
如果你来自其他编程语言,可能会让人感到困惑的一件事是,在Haskell中,你可以使用像
runState
Run Code Online (Sandbox Code Playgroud)
并添加一个参数
runState m
Run Code Online (Sandbox Code Playgroud)
它仍然是一个有效的功能.如果你然后添加第二个参数,如下所示:
runState m st
Run Code Online (Sandbox Code Playgroud)
它最终将计算一个值.这意味着if runState是两个参数的函数,那么它runState m是一个参数的函数,可以像对应一个参数的任何其他函数一样对待.
你的例子中重要的一点是
\st -> let (a, s) = runState m st in (f a, s)
Run Code Online (Sandbox Code Playgroud)
哪个可以变成
(\(a,s) -> (f a,s)) . runState m
Run Code Online (Sandbox Code Playgroud)
使用运算符进行函数组合(.).
理解如何实现的第一步是认识到let…in表达式可以用lambda形式重写.这意味着
let y = f x in expr
Run Code Online (Sandbox Code Playgroud)
可写成
(\y -> expr) (f x)
Run Code Online (Sandbox Code Playgroud)
这两行都将名称绑定y到值f x,这实际上是我们需要的let…in表达式.
如果你将这些知识应用于
\st -> let (a, s) = runState m st in (f a, s)
Run Code Online (Sandbox Code Playgroud)
你会看到它可以被重写为
\st -> (\(a, s) -> (f a, s)) (runState m st)
Run Code Online (Sandbox Code Playgroud)
我们就在那里!
功能组成的定义是这样的:
f . g = \x -> f (g x)
Run Code Online (Sandbox Code Playgroud)
这意味着每当你有一些看起来像\x -> f (g x)你可以用它替换它的东西f . g.
那么,在这种情况下,我们确实有类似的东西!如果我们这样说
f = \(a, s) -> (f a, s)
g = runState m
x = st
Run Code Online (Sandbox Code Playgroud)
我们看到了
\st -> (\(a, s) -> (f a, s)) (runState m st)
\x -> f (g x)
Run Code Online (Sandbox Code Playgroud)
只不过是等待发生的功能组合.所以我们可以把它变成
f . g
Run Code Online (Sandbox Code Playgroud)
这是我们对f和的定义g,
f . g
(\(a, s) -> (f a, s)) . (runState m)
Run Code Online (Sandbox Code Playgroud)
你可以放下括号runState m.
| 归档时间: |
|
| 查看次数: |
256 次 |
| 最近记录: |