2017-03-03 99 views
4

通过“从第一原理哈斯克尔编程”的工作,我的回答感到迷惑不解以下问题:哈斯克尔返回类型混乱

如果kessel类型为(Ord a, Num b) => a -> b -> a,那么 kessel 1 2类型是

一个)Integer
b)中Int
C)a
d)(Num a, Ord a) => a
E)Ord a => a
F)Num a => a

答案是d) - 但我认为答案应该是E),因为在类型签名的第一个参数,唯一的要求(a)为它是一个Ord。那么,为什么不回报?

kessel 'd' 2 

是有效的,这是Char类型 - 一无所知Num

我不明白什么?

谢谢你的帮助。

+4

我们要求'Num a'以便'1 :: a'有意义。 –

+4

作为一个侧面说明,这个问题真的很糟糕:“正确”的答案很大程度上取决于Haskell类型系统的一些不太有趣的变化,特别是默认和数字字面多态性,并取决于你如何解释这个问题还有单态限制。如果你对'Num b'约束使用了一个不同于'Num'的类(当然还有一个适当的'2'的替代参数),那么正确答案可能就是“这是一个模糊的类型错误”,如果你在文件中写入'foo = kessel 1 2',并向ghci询问它的类型,它会告诉你'foo :: Integer'! –

+1

......而且要明确,通过“这个问题”,我并不是说你要问的问题很糟糕。我认为你在设置你的问题方面做得很好。我在说“来自第一校长的Haskell编程”这个问题令人困惑,并且(在我看来)是一个严重的问题。 –

回答

5

1的类型是Num a => a。当您将其作为第一个参数传递给kessel时,其类型限制为(Num a, Ord a) => a,因为kessel需要Ord作为其第一个参数。由于结果的类型与第一个参数的类型相同,因此您会得到(Num a, Ord a) => a作为结果类型。

请注意,这与第二个参数的类型无关。我想第二个参数就是在那里混淆你。如果函数为:

kessel :: Ord a => a -> a 

那么kessel 1类型仍然是(Num a, Ord a) => aNum在那里,因为这是1的类型,而不是因为kessel的类型。

类型的kessel 'd' 2Char,相对于Ord Char => Char,因为Char是已经实现Ord一个具体类型,因此限制是不必要的。

+0

”...那么凯塞尔1的类型仍然是(数字a,奥德a)=> a。数字在那里,因为这是1的类型,不是因为凯塞尔的类型。啊......揭开了面纱。谢谢你。 – ericky

1

kessel 'd' 2

是有效的,这是Char类型 - 一无所知Num

是的! kessel 1 2kessel 'd' 2有不同的类型,

λ> kessel = undefined :: (Ord a, Num b) => a -> b -> a 
kessel :: (Num b, Ord a) => a -> b -> a 

λ> :t kessel 1 2 
kessel 1 2 :: (Num a, Ord a) => a 

λ> :t kessel 'd' 2 
kessel 'd' 2 :: Char 

这是可能的,因为kessel多态性