Система типов Haskell рассматривает численное значение как функцию?

После проигрывания вокруг с haskell немного я споткнулся эту функцию:

Prelude Data.Maclaurin> :t ((+) . ($) . (+))
((+) . ($) . (+)) :: (Num a) => a -> (a -> a) -> a -> a

(Данные. Maclaurin экспортируется векторным пространством пакета.), Таким образом, это берет Цифру, функцию, другую Цифру и в конечном счете возвращает Цифру. Что волшебство делает следующей работой?

Prelude Data.Maclaurin> ((+) . ($) . (+)) 1 2 3
6

2, очевидно, не функция (a-> a), или я пропускал что-то?

6
задан Don Stewart 18 April 2011 в 22:50
поделиться

2 ответа

Модуль Data.NumInstances того же пакета определяет экземпляр Num для функции, возвращающие числа:

instance Num b => Num (a->b) where
  (+)         = liftA2 (+)
  (*)         = liftA2 (*)
  fromInteger = pure . fromInteger
  ...

В Haskell целочисленный литерал, такой как 2 , является общим, поэтому он может представлять число для любого экземпляра Num :

Prelude> :t 2
2 :: (Num t) => t

Чтобы преобразовать его в фактическое число типа, требуемого в конкретном контексте, вызывается fromInteger из класса Num .

Поскольку упомянутый выше вспомогательный модуль определяет экземпляр Num для функций, 2 теперь можно преобразовать в функцию с помощью метода fromInteger . там указано. Итак, ghci вызывает fromInteger 2 , чтобы получить функцию, требуемую в качестве второго параметра конструкции в вопросе. Затем все выражение вычисляется как 6 .

16
ответ дан 8 December 2019 в 13:45
поделиться

У вас есть веская причина запутаться. Используя модуль Data.NumInstances в GHC (который загружается из Data.Maclaurin ), можно привести Num к постоянной функции.

Prelude Data.NumInstances> :t (2 :: (Num a) => a -> a)
(2 :: (Num a) => a -> a) :: (Num a) => a -> a
Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 0          
2
Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 1000
2

Вычисление выражения, по существу,

((+) . ($) . (+)) 1 2 3 = ((+) . ($) . (1+)) 2 3
                        = ((+) (1+)) 2 3
                        -- (+) is defined for functions that return a Num
                        = ((+) (1+) (\_ -> 2)) 3  
                        = ((+2) . (1+)) 3
                        = 6
1
ответ дан 8 December 2019 в 13:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: