Haskell:ConstraintKinds和TypeSynonymInstances之间的交互

时间:2018-10-28 05:55:20

标签: haskell constraint-kinds type-synonyms

当使用ConstraintKinds和TypeSynonymInstances尝试使用GHC 8.6.1编译小的Haskell文件时,出现意外错误。

我想创建一个以类作为参数的类,并且我想在编写实例时使用别名。这是代码:

{-# LANGUAGE ConstraintKinds, KindSignatures, TypeSynonymInstances #-}

module TypeAlias where

import Data.Kind

class Foo a
class Bar a

class Baz (c :: * -> Constraint)

instance Baz Foo -- compiles
instance Baz Bar -- compiles

type FooBar a = (Foo a, Bar a) -- compiles

instance Baz FooBar -- fails!
-- TypeAlias.hs:17:10-19: error:
--     • The type synonym ‘FooBar’ should have 1 argument, but has been given none
--     • In the instance declaration for ‘Baz FooBar’
--    |
-- 17 | instance Baz FooBar
--    |          ^^^^^^^^^^

该错误是令人惊讶的,因为据我所知,FooBar具有预期的类型,即* -> Constraint,但编译器表示应为其提供参数。

我在这里尝试在实例声明中甚至可以使用约束别名吗?如果是这样,我该如何看似矛盾的错误消息?

(我知道我可以简单地将FooBar声明为类而不是别名,但是我真的不想这么做,因为我也想要一个实例,那时候我必须插入UndecidableInstances。)

1 个答案:

答案 0 :(得分:0)

结果证明,埃德·克梅特(Ed Kmett)一年前回答了我的问题。我无法使用类型别名来做到这一点,但是对于这种特殊情况,使用UndecidableInstances应该是有益的:

https://www.reddit.com/r/haskell/comments/5zjwym/when_is_undecidableinstances_okay_to_use/

Kmett可能会建议修正上述示例:

{-# LANGUAGE ConstraintKinds, FlexibleInstances,
             KindSignatures, UndecidableInstances #-}

module NotTypeAlias where

import Data.Kind

class Foo a
class Bar a

class Baz (c :: * -> Constraint)

instance Baz Foo -- compiles
instance Baz Bar -- compiles

class (Foo a, Bar a) => FooBar a
instance (Foo a, Bar a) => FooBar a -- compiles

instance Baz FooBar -- compiles

Kmett认为,如果我们提供的FooBar实例是范围内的 sole 实例,则类型检查器不会因我们使用{{ 1}}。我很满意他的信。