Есть ли "комбинаторы уровня"? Будут ли они существовать в будущем? - программирование
Подтвердить что ты не робот

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

Большая часть того, что делает 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? Это даже полезно, или я просто бессвязно?

Edit:

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

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

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

...

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Ответ 3

Я пишу ответ здесь только для разъяснения вещей и рассказывать о достижениях в последние годы. В Haskell есть много возможностей, и теперь вы можете писать некоторые операторы в типе. Используя $ вы можете написать примерно так:

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

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

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