2014-09-18 2 views
0

Я пробовал Haskell после 'Haskell the hardway', и я застрял в понимании системы базового типа. У меня есть следующий код, и haskell жалуется, что он не может обработать функцию.Почему я не могу смешивать два примитива в функции?

f3 :: Num -> Int -> Num 
f3 x y = x + y 

Я принимаю его, он должен сделать что-то с выделки или базовая модель, в которой Haskell преобразует ф х у к (ф х) у, но если я хочу пройти и Int У, я могу это сделать? если я могу, как бы я это сделал?

+3

'Num' - это не тип, а тип. Также '(+)' ожидает, что оба аргумента будут одного типа. – Zeta

+0

Я не знал об этом ограничении. Исходя из императивного мира, разве это не было бы ограничительным? – Nair

+0

Я прочитаю предоставленную ссылку, спасибо. – Nair

ответ

5

Принимаю, это должно сделать что-то с выделкой или базовой моделью, где 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 бы сделать вывод.

1

Следующая причины:

1) Там нет такого типа, как Num

2) Оба аргументы (+) функции должны иметь тип же

Возможные решения:

f3 :: Int -> Int -> Int 

f3 :: Double -> Double -> Double 

f3 :: Num a => a -> a -> a  -- could add any numerical type 
+0

И многие другие комбинации, например. 'f3 :: Num a => Double -> Int -> a' – Zeta

+1

@Zeta Не с этим телом функции. – augustss

+0

@augustss: Правда, это не учитывалось. – Zeta