我开始尝试使用GHC 7.4.2中的新类约束扩展,但是我遇到了一些问题,让我们找到一个小例子。代码如下:
{-# LANGUAGE UndecidableInstances,
MultiParamTypeClasses,
KindSignatures,
TypeFamilies,
Rank2Types,
ConstraintKinds,
FlexibleInstances,
OverlappingInstances #-}
module Test where
import GHC.Exts -- to get Constraint type constructor
class NextClass f where
type Ctxt f a :: Constraint
next :: (Ctxt f a) => a -> a
instance NextClass Int where
type Ctxt Int a = Num a
next b = b + 1
n :: (NextClass a) => a -> a
n v = next v
我想要做的是定义一个NextClass
类型类,它允许我(给定值x)为NextClass
的所有类型获取x的下一个值。要使用+
运算符,我需要Num a
的{{1}}类约束。
但是,GHC给了我以下错误:
Int
我怀疑GHC告诉我它没有足够的信息来确定使用哪个约束族实例。
有人可以在这里解释我做错了什么。这是否正确使用约束族?
TIA
答案 0 :(得分:5)
你的定义中有一些奇怪的事情发生。首先,类变量f
从未在(仅)类方法next
的类型中提及。编译器应该如何选择要使用的类型类实例?我假设你的意思是:
{-# LANGUAGE ConstraintKinds, TypeFamilies #-}
module Test where
import GHC.Exts -- to get Constraint type constructor
class NextClass f where
type Ctxt f :: Constraint
next :: Ctxt f => f -> f
instance NextClass Int where
type Ctxt Int = Num Int
next b = b + 1
n :: (NextClass a) => a -> a
n v = next v
下一个奇怪的是Int
已经有Num
个实例,所以这不是一个约束。但是现在让我们把它放在一边(因为它不会影响我们得到的错误),只看一下新的错误:
test.hs:15:7:
Could not deduce (Ctxt a) arising from a use of `next'
from the context (NextClass a)
bound by the type signature for n :: NextClass a => a -> a
at test.hs:15:1-12
In the expression: next v
In an equation for `n': n v = next v
实际上,这个错误看起来很合理:约束的全部意义在于NextClass a
的实例是不够的;我们还必须有一个Ctxt a
的实例。所以我们可以修改类型签名:
n :: (NextClass a, Ctxt a) => a -> a
n v = next v
......然后编译。最后一个奇怪的是,这是一种特别简单的约束种类使用,因为这个更简单的代码基本上是等价的:
class NextClass f where
next :: f -> f
instance Num Int => NextClass Int where
next b = b + 1
...而且从之前的事物到新事物的翻译是非常机械的:而不是声明instance NextClass {- foo -} where type Ctxt {- foo -} = {- bar -}
,而只是写instance {- bar -} => NextClass {- foo -}
。