Поскольку 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
Longer объяснение
При использовании 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 = x
Что const magic
? Давайте начнем проще. Что такое const "Hello, World?"
?
const :: a -> b -> a
"Hello, World?" :: String
const "Hello, World?" :: b -> String
Мы заменили каждый вхождение a
с типом "Hello, World?"
«s. Теперь вернемся к нашему 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
«s оригинальный ограничение. Поэтому теперь у нас есть два ограничения: Num
и Ord
. Если мы теперь используем любой тип, который соответствует ограничению Num
, все, что у нас осталось, это na
. Так как это не на правой стороне больше, ее ограничение может быть отброшено:
kessel 1 2 :: (Num na, Ord na) => na
Это будет 'Integer' если вы уверить компилятор, что первый аргумент является' Integer', не является '' Int' Double' и т. Д. Итак, ': t kessel (1 :: Integer) 2' является' Integer' – Michael
Почему я не получаю просто 'Num' вместо' (Num a, Ord a) => a' –
Только первый аргумент вопросы. Это должно быть «Орд», потому что ты этого требовал. Это должно быть 'Num', потому что вы использовали числовой литерал. – Michael