Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
可以在Haskell中使(a,a)成为typeclass的成员吗_Haskell - Fatal编程技术网

可以在Haskell中使(a,a)成为typeclass的成员吗

可以在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

以下是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)’

问题是,实际上是否不可能使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
重新导出)。