我有以下类型的签名:
let kessel :: (Ord a, Num b) => a -> b -> a; kessel = undefined 当我询问结果类型时:
:t kessel 1 2我有:
kessel 1 2 :: (Num a, Ord a) => a为什么不Integer?
发布于 2017-02-21 11:32:42
因为1有Num a => a类型
ghci> :t 1
1 :: Num a => a
ghci> :t kessel
kessel :: (Num b, Ord a) => a -> b -> a
ghci> :t kessel 1
kessel 1 :: (Num a, Num b, Ord a) => b -> a
ghci> :t kessel 1 2
kessel 1 2 :: (Num a, Ord a) => a来自1 (Num)的约束被添加到已经存在的约束中。例如,当您使用id时,情况是相同的:
id :: a -> a
id 1 :: Num a => a较长解释
当您使用kessel :: (Ord a, Num b) => a -> (b -> a)时,您告诉编译器kessel将接受任何a,这是Ord的一个实例。然后,kessel将从任何其他(不一定不同)类型的b返回一个函数,这也是Num的一个实例,指向前面提到的a类型。
这意味着您为kessel使用的第一个参数将设置a
ghci> :t kessel (1 :: Int)
kessel (1 :: Int) :: Num b => b -> Int
ghci> :t kessel 'A'
kessel 'A' :: Num b => b -> Char
ghci> :t kessel "Hello, World!"
kessel "Hello, World!" :: Num b => b -> String在所有这些情况下,争论的类型是明确的。但是,如果我们使用的值是多态的呢?例如,这个:
magic :: Magic a => a也让我们使用一个更简单的函数,即const
const :: a -> b -> a
const x y = xconst magic是什么?让我们从简单的开始。什么是const "Hello, World?"?
const :: a -> b -> a
"Hello, World?" :: String
const "Hello, World?" :: b -> String我们将a的出现替换为"Hello, World?"的类型。现在回到我们的magic示例:
const :: a -> b -> a
magic :: Magic t => t
const magic :: Magic t => b -> t同样,我们将a的每次出现替换为我们的类型,在本例中是t。但是,我们不能忘记对t的附加约束,即Magic。我们必须把它带来。因此,我们在这里得到了附加的约束。但是,如果对a有任何限制,我们仍然必须将它们放到t上。
现在让我们回到您原来的kessel
kessel :: (Num b, Ord a ) => a -> b -> a
1 :: (Num n ) => n
kessel 1 :: (Num na, Ord na, Num b) => b -> na我们仍然保留a的原始约束。因此,我们现在有两个约束,Num和Ord。如果我们现在使用满足Num约束的任何类型,我们只剩下na。因为它不再在右边,它的约束可以被丢弃:
kessel 1 2 :: (Num na, Ord na) => nahttps://stackoverflow.com/questions/42365769
复制相似问题