显然有些心不在焉,我写了something like以下内容:
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}
class Foo f where
type Bar f :: *
retbar :: Bar f -> IO f
type Baz f = (Foo f, Eq f)
-- WithBar :: * -> (*->Constraint) -> * -> Constraint
type WithBar b c f = (c f, Bar f ~ b)
instance Foo () where
type Bar () = ()
retbar = return
naim :: WithBar () Baz u => IO u -- why can I do this?
naim = retbar ()
main = naim :: IO ()
只有在成功编译之后,我才意识到不应该实际工作:Baz
被定义为带有一个参数的类型同义词,但在这里我使用它而没有直接参数。当我尝试这样的事情时,GHC通常会盯着我Type synonym ‘Baz’ should have 1 argument, but has been given none
。
现在,不要误会我的意思:我真的希望能够写出来,并且很容易看到它在这个特定的例子中如何工作(简单地内联WithBar
会产生签名{{ 1}},这当然很好,但我不明白为什么它实际上就像这里一样。它可能只是naim :: (Foo u, Bar u ~ ()) => IO u
允许这个的错误吗?
答案 0 :(得分:8)
您的文件在GHC 7.8中编译,但在GHC 7.10中我收到错误:
类型同义词'Baz'应该有1个参数,但是没有给出
在'naim'的类型签名中:naim :: WithBar()Baz u => IO u
添加-XLiberalTypeSynonyms
可修复错误。因此,这是7.8中的错误。
答案 1 :(得分:4)
我不知道官方规则是什么,但是这种事情在最左边最类型的同义词扩展策略的基础上工作似乎是合理的。唯一重要的是类型同义词可以在其他类型检查发生之前在单独的和终止阶段处理。我不知道你是否打算使用部分应用的同义词F作为另一个类型同义词G的参数,只要G确保F接收其缺少的参数,但是&#39 ; s肯定与类型同义词是一种浅薄的便利性的想法一致。
答案 2 :(得分:3)
部分应用程序 应由LiberalTypeSynonyms
扩展程序启用。
基本上,这会延迟大多数类型同义词的一致性检查,直到它们被扩展为止,所以你的“内联”解释本质上是正确的想法。
但是,这里的奇怪之处在于,此扩展程序不隐含在您的模块中。我刚刚测试过,部分应用程序一般不适用于ConstraintKinds
,TypeFamilies
和PolyKinds
。 (我添加了后者,因为在扩展之前检查了各种 ,否则我的测试类型被推断为错误的。)
尽管如此,你的文件在GHCi 7.8.3中对我来说很好。也许这个 是某种错误,即使有一个扩展来使其合法化。