Приложение с частичной функцией Haskell с $ - PullRequest
0 голосов
/ 02 февраля 2019

Я новичок в Haskell и смотрю на простой пример использования приложения функции с $.

Это кажется простым - оно берет функцию и применяет ее к значению.

Так что это имеет смысл:

> (+3) $ 2
5

Это также имеет смысл:

> ($) (+3) 2
5

Это имеет смысл, потому что первый аргумент является функцией, а второй аргумент является значением.

Теперь рассмотрим использование $ для создания частичной функции.

Глядя на типы, это имеет смысл - просто нужно значение типа Num для b:

> :t ($) (+3)
($) (+3) :: Num b => b -> b

Но вот где я заблудился - что здесь происходит?:

> :t ($) (2)
($) (2) :: Num (a -> b) => a -> b

Я ожидал, что первый аргумент должен быть функцией, а не простым значением Num.

Вот мои вопросы:

  1. Что здесь происходит?
  2. Что означает синтаксис ограничения Num (a -> b)?
  3. Что является примером использования ($) втаким образом, это начинается с чего-то вроде ($) (2)?

Спасибо!

1 Ответ

0 голосов
/ 02 февраля 2019

С одной стороны, числовые литералы, такие как 2, на самом деле читаются как fromInteger 2 :: Num a => a, поэтому могут обозначать любое значение типа Num a => a, то есть любой тип, который в классе типов Numто есть имеет среди прочего определенную специальную версию fromInteger, которая возвращает фактическое значение фактического типа, преобразованное из целого числа 2:

> :i Num
class Num a where
  (+) :: a -> a -> a
  (*) :: a -> a -> a
  (-) :: a -> a -> a
  negate :: a -> a
  abs :: a -> a
  signum :: a -> a
  fromInteger :: Integer -> a

как Учебное пособие по Haskell ставит (в 10.3),

Целое число (без десятичной точки) фактически эквивалентно применению fromInteger к значению числа как Integer.

С другой стороны, ($) имеет тип

> :t ($)
($) :: (a -> b) -> a -> b

Итак, у нас есть

fromInteger 2 :: Num a1 =>   a1
($)           ::          (a -> b) -> a -> b
--------------------------------------------
($) 2         :: Num      (a -> b) => a -> b

Так что это функция, которая также должна быть в класс типов Num.

Обычно это не так, но Haskell не знает, можно ли импортировать какой-либо модуль, который определяет такой экземпляр:

instance Num (a -> b) where
   ....
   fromInteger n = ....
   ....

, поэтому он допускает такую ​​возможность при проверке типа, и только тогда, видя, что такой фактический экземпляр не определен нигде, выдает ошибку , что .

Например,следуя подсказке от @ augustss в комментариях,

instance (Num b) => Num (a -> b) where
   (+) f g x = f x + g x
   (*) f g x = f x * g x
   abs f x = abs (f x)
   negate f x = negate (f x)
   signum f x = signum (f x)
   fromInteger n = const (fromInteger n)

позволяет нам написать (sin + 2 * cos^2) x.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...