这是Haskell中的代码:
class Fooable a where
foo :: a -> a
instance Fooable (a, a) where
foo = ...
这样的代码无法在没有FlexibleInstances
扩展名的传统Haskell中编译。错误消息会说:
Illegal instance declaration for ‘Fooable (a, a)’
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use FlexibleInstances if you want to disable this.)
In the instance declaration for ‘Fooable (a, a)’
问题是,实际上不可能使元组(a, a)
成为任何类型类的成员,因为each type variable appears at most once in the instance head
?
答案 0 :(得分:6)
没有办法在实例中直接强制(a, b)
的关系(没有FlexibleInstances
或其他扩展名),但它们可能是等效的。
这意味着,如果Fooable (a, b)
是一个实例,那么如果a
可以等于b
,则Fooable (a,a)
也是一个实例。考虑获得更多实例。
然而,有一些方法:
newtype Tuple a = Tuple {unTuple :: (a, a)}
instance Fooable (Tuple a) where
foo = id
它不是这个星球上最漂亮或最好的东西,但至少在运行时它会表现得好像没有包装。
答案 1 :(得分:6)
如果您想使用其他扩展程序,可以编写
{-# LANGUAGE GADTs #-}
-- and/or
{-# LANGUAGE TypeFamilies #-}
instance a ~ b => Fooable (a, b) where
foo (a, b) = (b, a)
这将使Fooable (a, a)
成为实例,并确保没有其他对可以是实例(没有OverlappingInstances
)。然而,AJFarmar's answer对此有一种更愉快的感觉。