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

StackOverflow https://stackoverflow.com/questions/2496457

Вопрос

Немного поигравшись с Haskell, я наткнулся на эту функцию:

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

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

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

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

Это было полезно?

Решение

А 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.

Другие советы

У вас есть веская причина для замешательства.Используя 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top