Существуют ли «комбинаторы уровня типа»?Будут ли они существовать в будущем? - PullRequest
17 голосов
/ 23 ноября 2011

Многое из того, что делает haskell действительно хорошим для использования, на мой взгляд, это комбинаторы, такие как (.), flip, $ <*> и т. Д. Похоже, я могу создать новый синтаксис, когда мне это нужно.

Некоторое время назад я делал что-то, что было бы чрезвычайно удобно, если бы я мог «перевернуть» конструктор типов.Предположим, у меня есть конструктор типа:

m  :: * -> * -> * 

, и у меня есть класс MyClass, которому нужен тип с конструктором типа вида * -> *.Естественно, я бы предпочел закодировать тип таким образом, чтобы я мог сделать:

instance MyClass (m a) 

Но предположим, что я не могу изменить этот код, и предположим, что то, что действительно вписывается в MyClass, выглядит как1016 *

type w b = m b a 

instance MyClass w where 
    ...

и тогда мне нужно будет активировать XTypeSynonymInstances.Есть ли какой-нибудь способ создать «комбинатор уровня типа» Flip, который я могу просто сделать:

instance MyClass (Flip m a)  where 
   ...

??Или другие обобщения типа общих операторов, которые мы используем в haskell?Это даже полезно или я просто болтаю?

Редактировать:

Я мог бы сделать что-то вроде:

newtype Flip m a b = Flip (m b a)

newtype Dot m w a  = Dot m (w a)

...

Но тогда мне пришлось бы использовать конструкторы данных Flip, Dot, ..вокруг для сопоставления с образцом и т. д. Стоит ли это?

Ответы [ 3 ]

11 голосов
/ 24 ноября 2011

Ваш вопрос имеет смысл, но ответ таков: нет, в настоящее время это невозможно.

Проблема в том, что (в системе типов GHC Haskell) вы не можете иметь лямбды на уровне типов.Если вы попробуете что-то похожее на эмуляцию лямбды на уровне типов, вы обнаружите, что она не работает.(Я знаю, потому что я сделал.)

Что вы можете сделать, это объявить свои новые типы Flip, а затем написать экземпляры классов, которые вы хотите для них, мучительно с обертыванием и развертыванием (кстати: используйтесинтаксис записи), и тогда клиенты классов могут использовать новые типы в сигнатурах типов и не должны беспокоиться о деталях.

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

3 голосов
/ 24 ноября 2011

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

{-# LANGUAGE TypeFamilies, FlexibleInstances #-}
module Main where

class TFlip a where
    type FlipT a

instance TFlip (f a b) where
    type FlipT (f a b) = f b a 

-- *Main> :t (undefined :: FlipT (Either String Int))
-- (undefined :: FlipT (Either String Int)) :: Either Int [Char]

Также смотрите это предыдущее обсуждение: Лямбда для выражений типов в Haskell?

2 голосов
/ 27 марта 2017

Я пишу здесь ответ только для того, чтобы прояснить ситуацию и рассказать о достижениях за последние годы.В Haskell имеется множество функций, и теперь вы можете написать несколько операторов в виде.Используя $, вы можете написать что-то вроде этого:

foo :: Int -> Either String $ Maybe $ Maybe Int

, чтобы избежать скобок вместо старого доброго

foo :: Int -> Either String (Maybe (Maybe Int))
...