0

假设您有一个函数 f 将按如下方式使用:

(f f (x-1)) 

关于 f 的类型,你能推断出什么?

它似乎是递归的,即f :: (ftype) -> int -> int。

4

3 回答 3

3

如果函数的参数是该函数本身,那么该类型必须是递归的和无限的,这在 Haskell 中是非法的。然而,有一个漏洞:如果函数在那个参数中是多态的,那么它很好(尽管作为一个函数可能不是很有用)。有效的两个示例fidand const id(其中任何一个都f f (x-1)将评估为x-1)。

于 2019-12-28T16:52:22.730 回答
0

在您的标题中,您询问了f. 在通常的说法中,表达式的 HM 类型是通过应用于特定上下文的正式 HM 类型推断规则为表达式推断的主要(最一般)类型。因此,f没有上下文就没有类型,并且表达式f f (x-1)没有提供足够的上下文信息来键入f。上下文可以在“开始时”给出,也可以通过使用 lambda 或let表达式来开发。开发的上下文将确定是否可以推断出 HM 类型f,如果可以,那么该类型是什么。

例如,较大的表达式:

let f = \y -> y in \x -> f f (x-1)

可以在空上下文中键入。如果运算符是减法,它会推断整个表达式的类型和类型forall a. a -> a,而无需详细介绍。(HM 类型系统没有类型类和约束的概念,例如。)因此,这里的 HM 类型为is ,它在表达式中的使用并不会真正影响其类型。这对于用表达式引入的表达式很典型。例如,较大的表达式:fInteger -> Integer-IntegerNumfforall a. a -> af f (x-1)flet

let f = \y -> \z -> y in \x -> f f (x-1)

也很好打字。推断的类型fforall a b. a -> b -> a(这是显而易见的类型,\y -> \z -> y不受表达式其余部分的影响)。整体表达式有 type forall a b. Integer -> a -> b -> a

相反,如果f是通过 lambda 表达式引入的,那么情况就不同了,表达式f f (x-1)确实会影响 的推断类型f。例如,较大的表达式:

\f -> \x -> f f (x-1)

在 HM 中是错误类型的,因此不会f为整个表达式推断类型。如果双 lambda 的主体发生变化,则可以f根据表达式推断出不同的 HM 类型:

\f -> \x -> f (f x x) (x-1)   -- f :: Integer -> Integer -> Integer
\f -> \x -> f x + f x         -- f :: forall a. a -> Integer

fSooooo ...总之,仅从表达式中无法推断出任何类型,f f (x-1)因为上下文不足。在flet表达式引入的上下文中, 的类型f将严格从 的定义中推断出来f,只要类型与表达式 兼容f f (x-1),类型推断就会成功。相反,在f由 lambda 表达式引入的上下文中,表达式f f (x-1)是错误类型的,因此无法推断出 for 的f 类型

于 2019-12-28T22:17:05.720 回答
0

要回答这个问题,您可以应用类型推断算法。非正式地讨论它,您可以先说明这一点,f :: a -> b -> c因为它需要两个咖喱论点。您也可以推断出约束Num b,因为x - 1, 所以f :: Num b => a -> b -> c。如果您知道类型x是什么,可能会更多。但仅此而已。

例如,函数可以定义为f g x = undefined,在这种情况下,它的两个参数都被丢弃,并且返回类型不与任何输入类型统一。如果f有一个函数体,那么你可以推断出更多。

于 2019-12-28T05:58:25.973 回答