问题描述
请仅寻找此功能类型的说明
f x y z = x y (y z)
序曲说的是
f :: ((b -> a) -> a -> c) -> (b -> a) -> b -> c
但是我无法通过任何已知方法获得结果¬
最诚挚的问候。
解决方法
U,那些“手动键入此表达式的类型”练习非常愚蠢。我不知道为什么讲师会继续把他们安排在作业中。
实际上,实际上更相关的是走另一条路:给定类型,找到实现。因此,让我从这个角度回答这个问题:您已经知道
f :: ((b -> a) -> a -> c) -> (b -> a) -> b -> c
-- └──────────────────┘ └──────┘ └─┘
...因此您有三个参数可以接受,足够合理,可以将它们称为x
,y
和z
f x y z = _
您最终要寻找c
,而您唯一可用的c
就是x
的最终结果
x :: (b -> a) -> a -> c
-- └──────┘ └─┘
...这需要两个参数
f x y z = x _ _
...类型为b -> a
和a
的...。让我们检查一下可用的东西
y :: b -> a
z :: b
太好了,我们可以直接使用y
作为第一个参数
f x y z = x y _
对于第二个参数,我们需要一个a
。好吧,z
是b
,不起作用,但是当给定y
时a
会产生b
,因此我们可以传递{{1 }},最终以
y z
或者我们更喜欢用Haskell f x y z = x y (y z)
来写。
现在换一种方式:让我们从η简化形式开始
f x y = x y . y
这是一条管道,因此让我们开始为传递参数指定名称f x y = x y . y
p
该参数首先传递给 x y . y :: p -> _
,所以我们有
y
紧随其后的,因为 y :: p -> _
也是y
的第一个参数
x
此外, x :: (p -> _) -> _
然后接受(在管道中)从x
出来的任何内容
y
让我们将最终结果称为 y :: p -> r
x :: (p -> r) -> r -> _
q
并按照给定的方式编写整个功能:
y :: p -> r
x :: (p -> r) -> r -> q
重命名类型变量后,这与开始时的含义相同。
,在f x y z = x y (y z)
中,您可以进行以下推理:
-
我们不对任何事物应用
z
,因此它可以具有任意类型;称为u1
(代表未知的数字)。 -
y
应用于z
,因此其参数类型为u1
,但是返回类型为另一个未知类型u2
。因此y :: u1 -> u2
。 -
y z
的类型为u2
。 -
x
应用于y
和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
由于各个类型变量的名称除了将不同类型分开之外并不重要,因此我们可以使用
对其进行重命名-
u1 ~ b
-
u2 ~ a
-
u3 ~ c
获取您查找的类型
f :: ((b -> a) -> a -> c) -> (b -> a) -> b -> c