2015-03-19 2 views
3

Играя с TypeOperators Я пробовал реализовать $ и ., поэтому я могу избавить свою программу от любых круглых скобок (не обижайтесь ни на какие красивые Лисперсы там). При этом я изоморфно скопировал определения. Сначала я попытался использовать только $, потому что вам не нужно . с его мощной силой.Последовательность типов-операторов и требования к типу

{-# LANGUAGE TypeOperators #-} 
type f $ a = f a 

f :: Int -> IO $ Either String Int 
f n = undefined 

Отлично. Это компилируется, и я доволен.

{-# LANGUAGE TypeOperators #-} 
type f $ a = f a 

f :: Int -> IO $ Maybe $ Either String Int 
f n = undefined 

Это должно работать правильно?

TyCo.hs:4:18: 
    Expecting one more argument to ‘Maybe’ 
    The second argument of ‘$’ should have kind ‘*’, 
     but ‘Maybe’ has kind ‘* -> *’ 
    In the type signature for ‘f’: 
     f :: Int -> (IO $ Maybe) $ Either String Int 

Видимо нет.

{-# LANGUAGE TypeOperators #-} 
type f $ a = f a 
type (f * g) a = f (g a) 

f :: Int -> IO * Maybe $ Either String Int 
f n = undefined 

С слепой надеждой, я стараюсь.

TyCo.hs:5:6: 
    Type synonym ‘*’ should have 3 arguments, but has been given 2 
    In the type signature for ‘f’: 
     f :: Int -> (IO * Maybe) $ Either String In 

В моем невежественном ступоре я поднимаю вопрос: WHY она не работает?

+3

Для вашего первого примера это похоже на то, что ассоциативность '$' неверна. Я полагаю, что '$' на уровне значений и '$' на уровне типа считаются разными идентификаторами, и мы не объявили о приоритете или ассоциативности для последнего. Я не знаю, как это сделать, или если есть способ. По крайней мере, играйте с 'infixr' немного ... – luqui

+3

Вы также должны включить' PolyKinds' и/или 'LiberalTypeSynonyms', если вы ожидаете, что эти ярлыки будут в целом полезными. – luqui

+2

@ Комментарии luqui находятся на правильном пути. Вы можете исправить первую версию с 'infixr 0 $', а вторую версию - с помощью 'LiberalTypeSynonyms'. –

ответ

1

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

LiberalTypeSynonyms просто делает GHC UnWrap типа-синонимы, прежде чем он делает проверку типов, т.е. (IO * Maybe) $ Either String Int становится (IO (Maybe (Either String Int))) и затем его тип-чеки. Это означает, что * больше не применяется частично, и программа компилируется.

Смежные вопросы