Принимаю, это должно сделать что-то с выделкой или базовой моделью, где Haskell преобразующим е х у к (ф) х у
Нет, это имеет — как почти всегда в мире Haskell — делать с типами. Прежде всего, Num
- это тип, а не тип. Типами могут быть экземпляры, например Int
, Integer
и Double
являются экземплярами Num
. Теперь давайте посмотрим плюс плюс:
(+) :: Num a => a -> a -> a
Aha! Он принимает два аргумента типа a
и возвращает a
, где a
должен быть экземпляром Num
(также называемый ограничение).
Теперь у нас есть достаточно информации, чтобы пересмотреть f3
:
f3_wrong_sig :: Num -> Int -> Num
После вышесказанного, становится ясно, что f3_wrong_sig
имеет неправильную подпись. Вместо Num
, она нуждается в a
ограничен Num
:
f3_wrong_implementation :: Num a => a -> Int -> a
f3_wrong_implementation x y = x + y
Однако, если вспомнить тип (+)
, x + y
является единственно возможным для a
и Int
эквивалентными (также написано a ~ Int
). Нам нужен способ создать другой числовой тип от Int
: нам нужна функция Num a => Int -> a
. Позволяет проверять информацию о Int
в GHCi:
ghci> :i Int
data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in `GHC.Types'
-- omitted
instance Integral Int -- Defined in `GHC.Real'
instance Num Int -- Defined in `GHC.Num'
-- omitted
Int
не только экземпляр Num
, но и Integral
.Быстрый hoogle search дает нам fromIntegral :: (Integral b, Num a) => b -> a
, которые мы можем подключить и, наконец, получить то, что мы хотим:
f3 :: Num a => a -> Int -> a
f3 x y = x + fromIntegral y
В этот момент, мы можем также сделать последний шаг, чтобы сделать это еще более общий характер, так как fromIntegral
работ по любомуIntegral
:
f3_general :: (Integral b, Num a) => a -> b -> a
f3_general x y = x + fromIntegral y
Это также тип GHC бы сделать вывод.
'Num' - это не тип, а тип. Также '(+)' ожидает, что оба аргумента будут одного типа. – Zeta
Я не знал об этом ограничении. Исходя из императивного мира, разве это не было бы ограничительным? – Nair
Я прочитаю предоставленную ссылку, спасибо. – Nair