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
Haskell 通用量化(或多态)类型类实例_Haskell - Fatal编程技术网

Haskell 通用量化(或多态)类型类实例

Haskell 通用量化(或多态)类型类实例,haskell,Haskell,是否可以在Haskell中定义由类型a参数化的泛型类型类实例? 例如: data Box a = Box a deriving Show class Boxable a where create :: a -> Box a -- pseudo syntax here instance forall a . Boxable a where create = Box 若否,原因为何 我知道这个例子很简单,而且“毫无用处”。我只是想知道这在理论上是否可行,而不是它是否实际相关。您的

是否可以在Haskell中定义由类型
a
参数化的泛型类型类实例? 例如:

data Box a = Box a deriving Show

class Boxable a where
  create :: a -> Box a

-- pseudo syntax here
instance forall a . Boxable a where
  create = Box
若否,原因为何


我知道这个例子很简单,而且“毫无用处”。我只是想知道这在理论上是否可行,而不是它是否实际相关。

您的代码实际上是合法的Haskell,没有任何“伪语法”。它还不完全是Haskell 98,但它确实编译了两个非常无害的语法扩展:

{-# LANGUAGE ExplicitForall, FlexibleInstances #-}

data Box a = Box a deriving Show

class Boxable a where
  create :: a -> Box a

instance forall a . Boxable a where
  create = Box
显式
forall
(duh)需要
-XExplicitForall
†,但实际上您甚至不需要它,因为默认情况下Haskell类型变量是通用量化的:

{-# LANGUAGE FlexibleInstances #-}

instance Boxable a where
  create = Box
除此之外,就像chepner已经评论过的那样,这并没有真正意义,因为现在
create
的行为就像一个常规的参数化函数,不需要任何类型类:

create' :: a -> Box a
create' = Box
也就是说,如果您使用一些超类约束这些实例,那么这种一次性的实例实际上是有用的:

class Foo a
class Bar a

class (Foo a, Bar a) => FooBar a

instance (Foo a, Bar a) => FooBar a
现在,如果在函数的约束中提到
FooBar(somecomplementdtype)
,它与写出
(Foo(somecomplementdtype)、Bar(somecomplementdtype)具有相同的效果
,这可以显著消除代码和错误消息的混乱,还可以使项目在未来更加安全,因为您可以向
FooBar
添加或删除超类,而无需更改具有此约束的所有函数的签名

(使用
-XConstraintKinds
可以实现一个非常类似的事情,因为可以证明更直接的约束同义词
类型FooBar A=(Foo A,Bar A)
,但这带来了一个众所周知的问题,
类型
实际上并不是一个封装,但编译器可以随时解开它,这通常不是什么大问题,只是它会导致更混乱的类型错误消息。)



†您不会经常在Haskell文件中找到
-XExplicitForall
本身,因为它实际上只作为
-XScopedTypeVariables
-XRankNTypes
的一部分,这两者都是常见的,并启用
for all
关键字或
我更喜欢编写它(另外还需要
-XUnicodeSyntax
)。

这只会复制常规参数多态性;类型类的要点是支持非参数多态性。可以将其添加为answer@chepner!如果愿意,还可以详细说明您的评论。:)如果从代码中删除所有的,并启用几个扩展,它应该编译。(虽然它看起来不是很有用。)@NiklasVest因为它实际上并不约束类型,所以方法
create
相当于一个常规多态函数
create::a->Box a
。然而,我不会低估它在类型级(甚至种类级)编程中可能起到某种作用的可能性,这是一种结合了
约束
值的运算符的乘法标识。不需要使用Full
ScopedTypeVariables
。只是
ExplicitForAll
就可以了。回答得非常好。事实上,语法确实有效,这让我很高兴!另外,感谢您对约束用例的进一步阐述!约束同义词不是一流的,所以我更喜欢在可能的情况下提供类。我有时会使用模式
type FooF a b c=一些大的约束;类别FooF a b c=>Foo a b c;实例FooF a b c=>Foo a b c
。我也经常对类型族
FooF
执行此操作。