Существуют ли "комбинаторы уровня типа"? Будут ли они существовать в будущем?

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

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

m  :: * -> * -> * 

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

instance MyClass (m a) 

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

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 ответа

Решение

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

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

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

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

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

{-# 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?

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

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

избегать скобок вместо старого доброго

foo :: Int -> Either String (Maybe (Maybe Int))
Другие вопросы по тегам