【发布时间】:2016-11-26 17:08:31
【问题描述】:
如果我定义
fun id x = x
那么id自然就有'a -> 'a的类型
当然,id 0 的计算结果为 0,这非常合理。
既然这很有意义,我应该可以用一个函数来封装它:
fun applyToZero (f: 'a -> 'a) = f 0
希望applyToZero 的类型为('a -> 'a) -> int,而applyToZero id 的计算结果为0
但是当我尝试像上面那样定义applyToZero 时,SML/NJ 会给出一个奇怪的错误消息,开头是:
unexpected exception (bug?) in SML/NJ: Match [nonexhaustive match failure]
raised at: ../compiler/Elaborator/types/unify.sml:84.37
这几乎看起来像是编译器本身的一个错误。很奇怪,但可能。
但 PolyML 也不喜欢它(尽管它的错误消息不那么奇怪):
> fun applyToZero (f: 'a -> 'a) = f 0;
poly: : error: Type error in function application.
Function: f : 'a -> 'a
Argument: 0 : int
Reason: Can't unify int to 'a (Cannot unify with explicit type variable)
Found near f 0
以下确实有效:
fun ignoreF (f: 'a -> 'a) = 1
使用推断类型('a -> 'a) -> int。这表明创建这种类型的高阶函数并非不可能。
为什么 SML 不接受我对applyToZero 的定义?是否有任何解决方法可以让我定义它,使其类型为('a -> 'a) -> int?
动机:在我尝试解决this question 中的难题时,我能够定义一个int -> 'a -> 'a 类型的函数tofun 和另一个函数fromfun,其所需属性为fromfun (tofun n) = n 用于所有整数@ 987654344@。但是,我工作的fromfun 的推断类型是('int -> 'int) -> 'int)。我添加类型注释以便 SML 将其作为('a -> 'a) -> int 接受的所有尝试都失败了。我不想展示我对 fromfun 的定义,因为提出这个问题的人可能仍在解决这个难题,但 applyToZero 的定义会触发完全相同的错误消息。
【问题讨论】:
-
Haskell 确实支持 Andreas 描述的更高级别的类型。 Here are some practical use-cases [堆栈溢出]。 Minor pedantry:您不能将函数应用于 SML 中的类型,因为 SML 没有类型级函数(或依赖类型)。