0

在使用 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。)

4

1 回答 1

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我们提供的实例是范围内的唯一实例,那么类型检查器不会因我们使用UndecidableInstances. 我很满意他的话。

于 2018-10-29T19:07:51.493 回答