Лямбда для выражений типа в Haskell? - PullRequest
24 голосов
/ 01 ноября 2010

Есть ли в Haskell или конкретном компиляторе что-то вроде лямбды на уровне типа (если это даже термин)?

Чтобы уточнить, скажем, у меня есть параметризованный тип Foo a b и я хочу, чтобы Foo _ bбыть примером, скажем, Functor.Есть ли механизм, который позволил бы мне сделать что-то похожее на

instance Functor (\a -> Foo a b) where
...

?

Ответы [ 7 ]

24 голосов
/ 01 ноября 2010

Хотя sclv ответил на ваш прямой вопрос, я добавлю в сторону, что существует более одного возможного значения для «лямбда уровня типа».У Haskell есть множество операторов типов, но ни один из них не ведет себя как правильные лямбды:

  • Конструкторы типов: Операторы абстрактных типов, которые вводят новые типы.Учитывая тип A и конструктор типа F, приложение функции F A также является типом, но не несет никакой дополнительной информации (уровня типа), чем "this F применяется к A".
  • Полиморфные типы: Тип, подобный a -> b -> a, неявно означает forall a b. a -> b -> a.forall связывает переменные типа в своей области видимости, таким образом ведя себя как лямбда.Если мне не изменяет память, это примерно «заглавная лямбда» в Системе F.
  • Синонимы типов: Ограниченная форма операторов типов, которые должны быть полностью применены и могут создавать только базовые типы иконструкторы типов.
  • Классы типов: По существу функционирует от конструкторов типов / типов до значений с возможностью проверки аргумента типа (т. е. путем сопоставления с образцом в конструкторах типов примерно таким же образомчто шаблон регулярных функций соответствует конструкторам данных) и служит для определения предиката членства для типов.Они ведут себя больше как обычные функции в некоторых отношениях, но очень ограничены: классы типов не являются первоклассными объектами, которыми можно манипулировать, и они работают с типами только как входные (не выходные) и значения только как выходные ( определенно не вводится).
  • Функциональные зависимости: Наряду с некоторыми другими расширениями они позволяют классам типов неявно создавать типы как результаты, которые затем можно использовать в качествепараметры для других типов классов.Все еще очень ограничен, например, из-за невозможности принять другие классы типов в качестве аргументов.
  • Семейства типов: Альтернативный подход к тому, что делают функциональные зависимости;они позволяют определять функции для типов таким образом, который выглядит намного ближе к обычным функциям на уровне значений.Обычные ограничения по-прежнему применяются, однако.

Другие расширения ослабляют некоторые из упомянутых ограничений или предоставляют частичные обходные пути (см. Также: Хакерство типа Олега).Тем не менее, в значительной степени единственное, что вы нигде не можете сделать, - это именно то, о чем вы спрашивали, а именно: ввести новую область привязки с абстракцией анонимной функции.

17 голосов
/ 01 ноября 2010

Из TypeCompose:

newtype Flip (~>) b a = Flip { unFlip :: a ~> b }

http://hackage.haskell.org/packages/archive/TypeCompose/0.6.3/doc/html/Control-Compose.html#t:Flip

Кроме того, если что-то является функтором с двумя аргументами, вы можете сделать его бифунктором:

http://hackage.haskell.org/packages/archive/category-extras/0.44.4/doc/html/Control-Bifunctor.html

(или, в более поздних дополнениях категории, более общая версия: http://hackage.haskell.org/packages/archive/category-extras/0.53.5/doc/html/Control-Functor.html#t:Bifunctor)

7 голосов
/ 01 ноября 2010

Мне не нравится идея отвечать на мой собственный вопрос, но, по-видимому, по мнению нескольких людей на #haskell на Freenode, на Haskell нет лямбд на уровне типа.

5 голосов
/ 03 ноября 2010

EHC (и, возможно, также его преемник, UHC) имеют лямбды на уровне типов, но они недокументированы и не так мощны, как в языке с зависимой типизацией. Я рекомендую вам использовать язык с зависимой типизацией, такой как Agda (похожий на Haskell) или Coq (другой, но все же чистый функционал по своей сути, и может интерпретироваться и компилироваться либо лениво , либо строго!) Я склонен к таким языкам, и это, вероятно, 100-кратное превышение того, что вы просите здесь!

2 голосов
/ 01 ноября 2010

Самое близкое, что я знаю для получения лямбда-типа, это определение синонима типа.В вашем примере,

data Foo a b = Foo a b

type FooR a b = Foo b a

instance Functor (FooR Int) where
...

Но даже с -XTypeSynonymInstances -XF FlexibleInstances это не работает;GHC ожидает, что тип syn будет полностью применен в заголовке экземпляра.Может быть какой-то способ договориться с семействами типов.

1 голос
/ 01 ноября 2010

Да, что сказал Гейб, на что несколько отвечают типовые семьи:

http://www.haskell.org/haskellwiki/GHC/Type_families

0 голосов
/ 07 апреля 2019

В зависимости от ситуации вы можете заменить исходное определение типа «перевернутой» версией, а затем сделать синоним типа для «правильной» версии.

С

data X a b = Y a b

instance Functor (\a -> X a b) where ...

до

data XFlip b a = Y a b  -- Use me for instance decalarations
type X a b = XFlip b a  -- Use me for everything else

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