我正在学习一门 haskell 课程,因为我是一个初学者。有一个任务,我不能解决,虽然我尝试了很多次。
任务是确定以下功能的最一般类型:
f x _ False = x
f _ x y = maybe 42 (g y) x
假设我们知道g :: a -> [a] -> b
有人能帮我吗?谢谢
我试图确定y :: Bool, g :: Bool -> [Bool] -> b(?)
,但我不确定“x”应该是什么,因为从第一行开始,我们可以说它可以是maybe 42 (g y) x
,但表达式中还有一个“x”。
所以f
的类型可能是f :: [Bool] -> [Bool] -> Bool -> [Bool]
?
2条答案
按热度按时间icnyk63a1#
让我们从最通用的类型开始:该函数接受三个参数,因此返回一个项,因此我们首先假设
f
的类型为:我们看到第三个参数与
False
匹配,因此是Bool
,因此是c ~ Bool
。第一个子句也将第一个参数赋给x
,并返回x
,因此这意味着第一个参数的类型a
和返回类型d
是相同的,因此是a ~ d
。我们知道
maybe
的类型为maybe :: f -> (e -> f) -> Maybe e -> f
,42
是第一个参数,因此类型为f
。整型字面值可以为任何Num
类型,因此我们知道Num f
。由于maybe 42 (g y) x
的返回类型也是f
,并且我们知道它也是a
,因此我们知道f ~ a
。maybe 42 (g y) x
中的第三个参数是x
,这是f
调用中的 * 第二个 * 参数(不要与第一个子句混淆),因此我们知道b ~ Maybe e
。我们还可以看到一个调用
g y
和g :: g -> [g] -> h
。g y
的类型应该与maybe
调用的第二个参数的类型相匹配,因此这意味着e ~ [g]
和a ~ h
。y
在g y
调用中具有Bool
类型,因此这意味着g ~ Bool
,并且因此x1M35N1X函数具有类型x1M36N1X。现在,我们已经收集了以下类型和等价物:
因此,这意味着
f
具有类型:因此,最通用的类型是
f :: Num f => f -> Maybe [Bool] -> Bool -> f
,或者我们可以将参数重命名为f :: Num a => a -> Maybe [Bool] -> Bool -> a
。我们可以让
ghci
来做这项工作,例如:因此,这意味着
ghci
确认了该类型。wfveoks02#
首先要认识到,对于任何方程,方程中定义的任何变量都只限于该方程。特别是,这意味着第一行中的
x
与第二行中的x
没有任何关系。这是两个独立的变量,只是碰巧有相同的名称。现在,你已经正确地确定了
y :: Bool
和g :: Bool -> [Bool] -> b
对于一些未知的b
。因此,g y :: [Bool] -> b
接下来要注意的是,因为
maybe :: p -> (q -> p) -> Maybe q -> p
,这意味着q ~ [Bool]
(来自g y
类型)和p ~ Int
(来自字面量42
),因此,g :: Bool -> [Bool] -> Int
和x :: Maybe [Bool]
(因为它被用作maybe
的第三个参数)。最后,从第二个等式中,我们可以看到函数的返回类型是
maybe
返回的值,也就是Int
,因此,这也是第一个参数的类型,因为它在第一个等式中返回。把所有这些放在一起:
最后一击:实际上我撒了一点谎。字面量
42
并不是真正的Int
。这样的字面量可以是任何具有Num
类示例的类型。为了说明这一点,让我们用泛型类型替换签名中的Int
,并给予该类型一个Num
约束: