Haskell 通用量化(或多态)类型类实例
是否可以在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 若否,原因为何 我知道这个例子很简单,而且“毫无用处”。我只是想知道这在理论上是否可行,而不是它是否实际相关。您的
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
。然而,我不会低估它在类型级(甚至种类级)编程中可能起到某种作用的可能性,这是一种结合了约束
值的运算符的乘法标识。不需要使用FullScopedTypeVariables
。只是ExplicitForAll
就可以了。回答得非常好。事实上,语法确实有效,这让我很高兴!另外,感谢您对约束用例的进一步阐述!约束同义词不是一流的,所以我更喜欢在可能的情况下提供类。我有时会使用模式type FooF a b c=一些大的约束;类别FooF a b c=>Foo a b c;实例FooF a b c=>Foo a b c
。我也经常对类型族FooF
执行此操作。