Haskell 如何获取给定多态函数和表达式的类型?
以下是提示此帖子的考试问题: 试题: 考虑Haskell中二叉树的以下定义Haskell 如何获取给定多态函数和表达式的类型?,haskell,typing,Haskell,Typing,以下是提示此帖子的考试问题: 试题: 考虑Haskell中二叉树的以下定义 data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a) flatten Empty = [ ] flatten (Leaf l) = [l] flatten (Node t1 r t2) = (flatten t1) ++ (r : (flatten t2)) 根据该声明,树可以是:Empty、包含a类型元素的叶、或包含a类型元素的节点和两个树s 例如,以下表达
data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)
flatten Empty = [ ]
flatten (Leaf l) = [l]
flatten (Node t1 r t2) = (flatten t1) ++ (r : (flatten t2))
根据该声明,树可以是:Empty
、包含a
类型元素的叶
、或包含a
类型元素的节点和两个树
s
例如,以下表达式具有类型树Int
:
Leaf 0
Node (Leaf 1) 2 (Leaf 3)
下面的函数将树
展平为元素列表(回想一下,++
是Haskell中列表的串联运算符)
一,。为函数flatten
提供多态类型。证明你的答案是正确的
二,。为表达式指定一个类型:
证明你的答案是正确的
我的问题
我想我理解这里的理论,很明显,展平
,为了完成它的工作,接受多种类型([]
,叶
和节点
),但我应该如何从中解释它的类型呢?除非我假设flatte
与它接受的类型相同,否则我不确定从这里开始该怎么做
关于问题的第二部分,flatte
是否有不同的类型取决于它是否以表达式的形式出现?如果是这样的话,我觉得我在最后一段中的假设是正确的,但我希望我能从实际的逻辑中得到安慰,而不仅仅是猜测
提前谢谢
很明显,flatten
,为了完成它的工作,它接受多种类型([]
,Leaf
和节点
)
我不明白你为什么认为flatten
接受[]
。我甚至不知道你这是什么意思[]
不是一个类型,它是一个类型构造函数,它将类型a
作为参数,并返回类型[a]
“其元素类型为a
”的列表
定义plant
的三个子句都使它成为一个接受一个参数的函数,因此它的类型为x->y
,其中x
是参数的类型,y
是返回类型。在每种情况下,参数都是通过应用树
类型构造函数的构造函数形成的,因此参数的类型为树w
。第一个子句中的返回值是[]
,因此其类型为[z]
。到目前为止,我们知道最常见的flatten
类型是树w->[z]
。第二个子句flatten(Leaf l)=[l]
提供了一个额外的约束w=z
,因为l
的类型出现在两侧,所以最常见的类型是树z->[z]
这实际上是展平
的有效类型,因此树z->[z]
是展平
的最通用类型。要看到这一点,您需要浏览整个定义,并检查它是否没有对z
施加任何附加约束
这是一个多态类型:它包含类型变量z
。此变量可以由任何类型实例化。例如,flatten(Leaf(1::Int))
对类型树Int->[Int]
使用flatten
,而flatten(Leaf True)
对类型树Bool->[Bool]
使用flatten
事实上,flatten
是多态的,并不是因为它是一个函数。将其应用于参数不会改变展平的类型,但它可能不会完全通用地使用它。结果表达式的类型仍然可以是多态的。例如,对于所有a
,\x->flatten x
的类型是树a->[a]
,与flatten
相同,这并不奇怪,因为\x->flatten x
等同于flatten
flant(Leaf 3)
的类型来自三个约束:flant
的参数类型为树a
的返回类型为[a]
,Leaf
接受任何类型a
并返回树a
,而3
的返回类型为Num a=>a
,即,3
具有任何类型a
,前提是该类型是Num
类的实例。因此,flatten(叶3)
具有类型[a]
,在约束条件下,a
是Num
的一个实例,即flatten(叶3)
具有最通用的类型Num a=>[a]
要正确理解这个问题,您应该知道
和。Haskell使用类型推断算法,但由于试题的知识是不必要的,而且直觉是充分的,所以试题的措辞是合理的。如果您在GHCI中键入:t
,它将为您提供类型,这一点也很有用
在此特定示例中,您的定义创建了四个构造函数-一元类型构造函数树
、空数据空
、一元数据叶
、三元数据节点
现在,我们来看看函数。函数有三个基于模式匹配的定义,但是我们知道每个定义必须具有相同的类型(或者可以与其他类型统一)。从第一行开始
flatten Empty = [ ]
我们可以看到,flatte获取一些空的
(我们知道的是一个树
的数据构造函数),并返回一个[]
,即一个列表。但是,树
是参数化类型<代码>空
但是不使用参数化,因此它可以属于任何树
-一个polymorfous类型树a
。[]
是一个列表。列表通常为[a]
类型,a
是列表的成员类型。没有成员
flatten Empty = [ ]
flatten Empty = ['e']
flatten (Leaf l) = [l]
flatten (Node t1 r t2) = (flatten t1) ++ (r : (flatten t2))