2015-03-19 69 views
3

TypeOperators交战我试过执行$.,所以我可以清除我的程序中的任何括号(对任何美丽的Lispers都没有任何攻击)。这样做我已经同构复制了定义。首先我试图只使用$,因为你不应该需要.它的强大的力量。类型运算符和类型要求的序列

{-# 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 2015-03-19 06:25:21

+3

如果你期望这些快捷键通常有用,你还应该启用'PolyKinds'和/或'LiberalTypeSynonyms'。 – luqui 2015-03-19 06:27:19

+2

@ luqui的评论都是正确的。你可以用'infixr 0 $'修复第一个版本,用'LiberalTypeSynonyms'修复第二个版本。 – 2015-03-19 06:59:56

回答

1

第一个问题与$的固定性有关,您可以通过注意括号的放置位置来看到错误信息中的符号。 (IO $ Maybe)是部分应用的类型同义词,导致错误。你不能部分应用类型同义词,因为它需要比较它们,这相当于比较函数。

LiberalTypeSynonyms只是使GHC解包类型的同义词它之前的类型检查,即(IO * Maybe) $ Either String Int变得(IO (Maybe (Either String Int)))然后它键入的检查。这意味着*不再部分应用,并且程序编译。