С помощью -XTypeApplications
в GHC 8.0 вы можете явно указывать типы с помощью @
предшествующих аргументов функции. Какие именно типы он указывает, особенно когда вводится несколько @
?
Как вы используете TypeApplications в Haskell?
Ответы (1)
Если вы посмотрите на тип функции
elem :: (Foldable t, Eq a) => a -> t a -> Bool
мы видим, что у него есть две полиморфные переменные, t
и a
. Эти переменные указывают приложения типа @
. Кажется, что переменные, введенные в контексте — там, где ограничения класса типов — влияют на порядок, и, следовательно, первый @
определяет t
, а второй a
. В функциях без переменных контекста
const :: a -> b -> a
порядок более очевиден, a
первый, а b
второй. Как упоминалось Cactus в комментарии выше, вы также можете использовать явные foralls, чтобы указать порядок самостоятельно.
myConst :: forall b a. a -> b -> a
Теперь приложение первого типа будет указывать b
, а второе — a
.
Вы можете столкнуться с этой проблемой необходимости указывать типы, особенно если вы используете перегруженные строки или списки.
elem c "abc...xyz" -- What string type is this?
elem c ['a' .. 'z'] -- What list constructor is this?
поэтому мы используем приложения явного типа
elem @[] @Char c ['a' .. 'z']
в этом случае мы только должны указать @[]
и сказать "это конструктор типа списка []
", потому что GHC выводит Char
из элементов списка, поэтому @Char
здесь можно опустить.
Если полиморфный аргумент, который GHC может вывести, оказывается первым, вы можете использовать -XPartialTypeSignatures
, который позволяет вам использовать _
в подписях типов, включая подписи приложений типов, говоря GHC просто вывести этот [часть] типа, чтобы сделать вещи менее подробными.
f @_ @[]
::
исчезло, особенно потому, что нужно вспомнить порядок ограничения типа. По крайней мере, в этом случае я бы посчитал elem c ['a' .. 'z'] :: [Char]
гораздо более читаемым.
- person MauganRa; 04.05.2018
ExplicitForAll
(илиTypedScopeVariables
, который его включает), если вы собираетесь использоватьTypeApplications
, поскольку в этом случае нет двусмысленности: если у вас есть, например.const :: forall a b. a -> b -> a
, то первый@
-аргумент будет дляa
, а второй дляb
. - person Cactus   schedule 27.10.2016