我目前需要进行一些大脑训练,我在Haskell and 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)
这匹配curry with rndf2
作为第一个参数。
但我不明白的是......
:t bind rndf2 . rndf1
突然给出
bind rndf2 . rndf1 :: (Num a, Num c) => a -> c -> (a, c)
这是我们试图制作的正确的合成类型,因为
bind rndf2 . rndf1
是一个功能:
rndf1
rndf1
获取回报并将其作为rndf2
的输入进行管道,以返回与rndf2
相同的类型 rndf1
可以使用2个参数a -> c
和rndf2
返回(a, c)
,因此它匹配这些函数的组合应具有类型:
bind rndf2 . rndf1 :: (Num a, Num c) => a -> c -> (a, c)
这与我最初提出的绑定
的天真类型不符bind f :: (a -> b -> (c, d)) -> (c, d) -> (e, f)
这里bind
神秘地采用一个函数,该函数接受两个参数并生成一个带有元组的函数,以便rndf1
的输出可以输入rndf2
答案 0 :(得分:0)
bind
应该有两个功能。您的“初始”类型签名需要一个函数和一个元组,并生成一个元组。这并不适用于这个问题:rndf1
不是一个元组,它是一个函数。一旦将参数应用于它,只有那时rndf1 a s
才会成为元组。所以bind
需要是一个带有两个函数的函数。
将元组管理为带有两个参数的函数的神秘力量在bind
的定义中。
bind :: (a -> c -> (b,c)) -> (c -> (a,c)) -> (c -> (b,c))
bind f x seed = let (x',seed') = x seed
in f x' seed'
在此定义中,f
和x
都是函数(如果您将x
重命名为g
,可能会更清楚。)
选择let (x',seed') = x seed
。 x seed
产生一个元组。在等号的左侧,该元组的各个元素被赋予新名称,然后在下一行将这些名称传递给函数f
。
因此,可能有助于细分表达式bind rndf2 . rndf1
。
请记住,所有函数实际上只有一个参数。 rndf1
的类型可以最准确地编写为(Num a , Num b) => a -> (b -> (a,b))
。这对了解以下内容非常有帮助。
另一件有用的事情是考虑如何将这个表达式与参数一起使用。例如:(bind rndf2 . rndf1) a s
。
由于所有函数都有一个参数,因此它们会逐个发送到括号内部。首先:((bind rndf2 . rndf1) a) s
。
现在,您可以在不使用.
运算符的情况下重写表达式:(bind rndf2 (rndf1 a)) s
。 a
传递给rndf1
,因为这就是.
的工作原理:点右侧的函数接受输入,然后将其输出传递给左侧的函数。 / p>
您会看到rndf1 a
的类型签名与bind
的第二个参数匹配。然后将参数rndf2
和(rndf1 a)
应用于bind
:
bind rndf2 (rndf1 a) seed = let (x', seed') = (rndf1 a) seed
in rndf2 x' seed'
现在,括号内的函数只需要一个seed
参数。因此,您可以使用s
并将其应用于函数:
bind rndf2 (rndf1 a) s = let (x', seed') = (rndf1 a) s
in rndf2 x' seed'