eal*_*ber -1 logic haskell types functional-programming declarative
只是寻找这个函数类型的解释,请
f x y z = x y (y z)
前奏说的是
f :: ((b -> a) -> a -> c) -> (b -> a) -> b -> c
但我无法用任何已知的方法得到那个结果 ¬¬
此致。
呃,那些“手动检查这个表达式”的练习太愚蠢了。我不知道为什么讲师总是把他们放在作业中。
在实践中,实际上更相关的是反过来:给定一个类型,找到一个实现。那么让我从这个角度回答这个问题:你已经知道了
f :: ((b -> a) -> a -> c) -> (b -> a) -> b -> c
-- ???????????????????? ???????? ???
Run Code Online (Sandbox Code Playgroud)
...所以你有三个参数可以接受,足够合理地调用它们x,y并且z
f x y z = _
Run Code Online (Sandbox Code Playgroud)
你最终在寻找一个c,而c你唯一可用的是在最终结果中x
x :: (b -> a) -> a -> c
-- ???????? ???
Run Code Online (Sandbox Code Playgroud)
...这需要两个参数
f x y z = x _ _
Run Code Online (Sandbox Code Playgroud)
...的类型b -> a和a。让我们检查一下我们有什么可用的
y :: b -> a
z :: b
Run Code Online (Sandbox Code Playgroud)
太好了,我们可以直接y用作第一个参数
f x y z = x y _
Run Code Online (Sandbox Code Playgroud)
对于第二个参数,我们需要一个a. 嗯,z是 a b,这不起作用,但是当给定 a 时会y产生a一个b,所以我们可以通过y z,因此最终得到
f x y z = x y (y z)
Run Code Online (Sandbox Code Playgroud)
或者我们更喜欢用 Haskell 编写它,f x y = x y . y.
现在反过来:让我们从 ?-reduced 形式开始
f x y = x y . y
Run Code Online (Sandbox Code Playgroud)
这是一个管道,所以让我们开始给传递参数一个名字 p
x y . y :: p -> _
Run Code Online (Sandbox Code Playgroud)
该参数首先传递给y,所以我们有
y :: p -> _
Run Code Online (Sandbox Code Playgroud)
它由此而来,因为y也是第一个参数x
x :: (p -> _) -> _
Run Code Online (Sandbox Code Playgroud)
此外,x然后接受(在管道中)任何来自y
y :: p -> r
x :: (p -> r) -> r -> _
Run Code Online (Sandbox Code Playgroud)
让我们调用最终结果 q
y :: p -> r
x :: (p -> r) -> r -> q
Run Code Online (Sandbox Code Playgroud)
并按照给定的方式写出整个函数:
(\x y -> x y . y) :: ((p -> r) -> r -> q) -> (p -> r) -> p -> q
-- ??????????x????????? ???y????
Run Code Online (Sandbox Code Playgroud)
也就是说,在重命名类型变量后,与您开始时的相同。
从f x y z = x y (y z),您可以推理如下:
我们不应用于z任何东西,所以它可以有一些任意类型;调用它u1(对于未知的第一)。
y应用于z,因此其参数类型是u1,但返回类型是另一种未知类型u2。因此y :: u1 -> u2。
y z因此有类型u2。
x应用于y and y z,所以必须有一个像(u1 -> u2) -> u2 -> u3; 没有理由假设任一参数具有相同的类型,或者任一类型与返回类型相同。
的返回值f与 的返回值相同x,即u3。
综上所述,我们有
f :: ((u1 -> u2) -> u2 -> u3) -> (u1 -> u2) -> u1 -> u3
------------------------ ---------- -- --
type of x type of y type of z end result of f
Run Code Online (Sandbox Code Playgroud)
因为除了保持不同类型分开之外,各个类型变量的名称并不重要,我们可以使用
u1 ~ bu2 ~ au3 ~ c获取您查找的类型
f :: ((b -> a) -> a -> c) -> (b -> a) -> b -> c
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
133 次 |
| 最近记录: |