haskell - 高级类型类的量化约束

标签 haskell quantified-constraints

假设我想写两个类型类。
标题:

{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE UndecidableInstances #-}

import Data.Complex
第一个类型类 ExClass 定义如下:
class (forall a. (Monoid (t a))) => ExClass t where
    exFunc :: [t (Complex a)] -> t (Complex a)
    exFunc = mconcat -- the actual function is more complicated
    exFunc2 :: (RealFloat a) => t (Complex a) -> a
我将它定义为更高级的类型类,因为它的一个函数的输出类型取决于其嵌套值的类型 a .我还想为 exFunc 设置一个默认实现,但它涉及假设t a是幺半群。现在我想为以下类型编写一个实例:
newtype ExType a = ExType a
ExType a只有当 Num a 时才是幺半群是真的:
instance (Num a) => Semigroup (ExType a) where
    ExType a <> ExType b = ExType (a * b)
instance (Num a) => Monoid (ExType a) where
    mempty = ExType 1
现在我继续为 ExClass 定义类型类实例,指定约束 Num a :
instance (forall a. Num a) => ExClass ExType where
    exFunc2 (ExType a) = magnitude a
上面的代码编译没有问题。但是,如果我尝试像这样使用已实现的函数:
x = ExType 2 :: ExType (Complex Double)

func = exFunc2 x
我收到以下投诉:
• No instance for (Num a) arising from a use of ‘exFunc2’
  Possible fix: add (Num a) to the context of a quantified context
• In the expression: exFunc2 x
  In an equation for ‘func’: func = exFunc2 x
当我使用不同的实例声明时也会发生这种情况:
instance (forall a. Monoid(ExType a)) => ExClass ExType where
    exFunc2 (ExType a) = magnitude a
有没有办法让这个类型类工作?或者我根本不应该像这样构建我的程序?

最佳答案

Daniel Wagner 已经在他的回答中解释了当前定义的问题。
看来你要ExClass意思是“一类容器类型与应用于其元素的另一个类 c 具有特殊关系,并且当它们的元素满足 c 时,容器本身就是幺半群”。
例如:ExTypeNum有特殊关系.当元素aExType满足 Num , ExType a变成 Monoid .
(这已经在 ExType s Monoid 实例中得到确认,但似乎您想用更高的抽象级别来表达它;为那些以类似方式成为幺半群的容器创建一个类。)
在 Haskell 中,有多种可能的方式来表达两种类型之间的关系——或者类型和 Constraint 之间的关系。 .让我们使用 MultiParameterTypeClasses :

{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ConstraintKinds #-}

import Data.Kind (Type, Constraint)
-- This kind signature is not strictly required, but makes things clearer
type ExClass :: (Type -> Constraint) -> (Type -> Type) -> Constraint
class (forall a . c a => Monoid (t a)) => ExClass c t | t -> c where
    exFunc :: c a => [t a] -> t a
    exFunc = mconcat 
请注意 ExClass现在有两个参数,即类型 f容器的(通过函数依赖)确定约束 c这是 f 的元素所必需的为 f成为 Monoid . c可能因不同而不同 f !SemigroupMonoid ExType 的实例不要改变。 ExClass ExType 的实例现在是:
instance ExClass Num ExType where
    exFunc = mconcat
让它工作:
main :: IO ()
main = print $ exFunc [ExType (1::Int), ExType 2]
(我遗漏了 Complex 数据类型,这可能会给定义带来另一个麻烦。)

关于haskell - 高级类型类的量化约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69529835/

相关文章:

haskell - groupBy 的 Lambda 参数

haskell - 元组 Ord 的定义

Haskell:将函数作为参数传递时出现刚性类型变量错误

haskell - GHC 9 中量化约束的行为变化

haskell - 如何使用范围内的约束系列来证明表达式主体内的实例?

sorting - 按第二个元素对元组列表进行排序

haskell - 出现歧义 '=='

haskell - 如何从范围内的约束族派生类型类实例?

haskell - 为什么使用 QuantifiedConstraints 指定类型类的子类还需要子类的实例?