我目前需要一些大脑训练,我在Haskell 和 Monads上找到了这篇文章
我在练习 7 时遇到问题。随机函数绑定。
为了使问题更易于实验,我将StdGen
类型替换为未指定的类型。所以,而不是...
bind :: (a -> StdGen -> (b,StdGen)) -> (StdGen -> (a,StdGen)) -> (StdGen -> (b,StdGen))
我用了...
bind :: (a -> c -> (b,c)) -> (c -> (a,c)) -> (c -> (b,c))
以及实际的功能实现(直接来自练习)
bind f x seed = let (x',seed') = x seed
in f x' seed'
还有 2 个随机函数可供试用:
rndf1 :: (Num a, Num b) => a -> b -> (a,b)
rndf1 a s = (a+1,s+1)
rndf2 :: (Num a, Num b) => a -> b -> (a,b)
rndf2 a s = (a+8,s+2)
因此,在 Haskell 编译器(ghci)中,我得到...
:t bind rndf2
bind rndf2 :: (Num a, Num c) => (c -> (a, c)) -> c -> (a, c)
这与rndf2
作为第一个参数的绑定 curried 匹配。
但我不明白的是如何...
:t bind rndf2 . rndf1
突然给
bind rndf2 . rndf1 :: (Num a, Num c) => a -> c -> (a, c)
这是我们正在尝试制作的正确类型的作品,因为
bind rndf2 . rndf1
是一个函数:
- 采用相同的参数类型
rndf1
- AND 接受 return from
rndf1
并将其作为输入rndf2
以返回相同的类型rndf2
rndf1
可以采用 2 个参数a -> c
并rndf2
返回(a, c)
,因此它匹配这些函数的组合应具有的类型:
bind rndf2 . rndf1 :: (Num a, Num c) => a -> c -> (a, c)
这与我最初为 bind 提出的幼稚类型不匹配
bind f :: (a -> b -> (c, d)) -> (c, d) -> (e, f)
这里bind
神话般地接受一个接受两个参数的函数并产生一个接受一个元组的函数,以便可以将输出rndf1
输入rndf2
- 为什么绑定函数需要按原样编码
- 为什么绑定函数没有天真的类型