可以在Haskell中使(a,a)成为typeclass的成员吗
以下是Haskell中的代码:可以在Haskell中使(a,a)成为typeclass的成员吗,haskell,Haskell,以下是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 f
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)’
问题是,实际上是否不可能使tuple
(a,a)
成为任何类型类的成员,因为每个类型变量在实例头中最多出现一次
?没有办法在实例中直接强制执行(a,b)
的关系(没有FlexibleInstances
或其他扩展),但它们可能是等效的。
这意味着如果<代码>可执行(a,b)<代码>是一个实例,那么如果<代码> a <代码>可以等于<代码> b>代码>,<代码>可执行(a,a)< /c>也是一个实例。考虑获取更多实例。
但是,有一种解决方法:newtype Tuple a = Tuple {unTuple :: (a, a)}
instance Fooable (Tuple a) where
foo = id
它不是这个星球上最漂亮或最好的东西,但至少在运行时它会表现得好像没有包装器一样。如果您想使用其他扩展,您可以编写
{-# LANGUAGE GADTs #-}
-- and/or
{-# LANGUAGE TypeFamilies #-}
instance a ~ b => Fooable (a, b) where
foo (a, b) = (b, a)
这将使
Fooable(a,a)
成为一个实例,并确保没有其他对可以成为实例(没有OverlappingInstances
)。但是,它的感觉更愉快。你确定吗?如果我启用FlexibleInstances
,并在(a,a)
上定义一个实例,我就可以让它工作(例如foo(x,y)=(x*2,y*7)
实例限制为numa
)。然后我可以对(Int,Int)
类型的值使用foo
,但不能对(Int,Float)类型的值使用
@SamvanHerwaarden是与FlexibleInstances一起的
,这是一个GHC特定的扩展,而不是vanilla Haskell。此外,这个问题似乎排除了扩展的可能性。这不是一个扩展吗?我当然忘记了!@AJFarmar,它当然是一个扩展,正如第一行所说的!我似乎找不到任何文档在它上面,当我搜索类型相等时,只有包?@AJFarmar,你可以通过GADTs
或TypeFamilies
获得特定的约束。类型级别的版本,:~:
,来自Data.Type.Equality
(由Data.Typeable
重新导出)。