haskell - 如何创建一个类型类来表示包含可提取 `Num` 实例类型的容器?

标签 haskell typeclass type-families

一段时间以来,我一直在努力在 Haskell 的类型系统中表达某种模式。我什至很难解释它(我想我对这个问题的理解还不够好,无法制定它),但是就这样! (并提前感谢任何能够理解并回答我的问题的无畏冒险者!)

假设我们有两种不同的容器类型,ContFContD ,其中每一个都只是一个 ADT,其中包含一个值 FloatDouble ,分别(在本例中它们也可能是新类型)。

我们想编写一个适用于任何一种类型的多态函数。也许它会提取该值并将其加 1(因此我们有一个 Num 约束)。所以我们创建了一个类型类,Cont ,具有提取值的功能。

我们不能只拥有 num原型(prototype)为 num :: (Num n) => t -> n ,因为那样我们会得到“无法推断 Float ~ n”的编译时错误;所以我们引入了一个关联的类型族。

{-# LANGUAGE TypeFamilies #-}

data ContF = CF Float
data ContD = CD Double

class Cont t where
    type family ContNum t :: *
    num :: t -> ContNum t

instance Cont ContF where
    type ContNum ContF = Float
    num (CF f) = f

instance Cont ContD where
    type ContNum ContD = Double
    num (CD d) = d

contAdd1 :: (Cont t, Num n) => t -> n
contAdd1 t = num t + 1

但是,当我尝试编译它时,出现以下错误。
Could not deduce (n ~ ContNum t)
from the context (Cont t, Num n)
  bound by the type signature for contAdd1 :: (Cont t, Num n) => t -> n

也许我想问的是:如何创建一个类型类来表示包含可提取 Num 的容器实例类型?
另外,请注意,这是一个非常人为的示例,用于展示我希望理解的内容。

最佳答案

答案在错误消息中。您需要以某种方式告诉编译器 n实际上是ContNum .

你可以做

contAdd1:: (Cont t, Num n, n ~ ContNum t) => t -> n

或者不要使用 n根本
contAdd1 :: (Cont t, Num (ContNum t)) => t -> ContNum t

但最后一个需要 FlexibleContexts延期。

这是您问题的第一部分,如何编译。要回答有关如何在类型类级别移动约束的问题?只需添加它。有用 :-)
{-# LANGUAGE TypeFamilies, FlexibleContexts #-}

data ContF = CF Float
data ContD = CD Double

class Num (ContNum t) =>  Cont t where
    type family ContNum t :: *
    num :: t -> ContNum t

instance Cont ContF where
    type ContNum ContF = Float
    num (CF f) = f

instance Cont ContD where
    type ContNum ContD = Double
    num (CD d) = d

contAdd1 :: (Cont t) => t -> ContNum t
contAdd1 t = num t + 1



> contAdd1 (CF 4)
 5.0

关于haskell - 如何创建一个类型类来表示包含可提取 `Num` 实例类型的容器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26218827/

相关文章:

haskell - 使用索引容器中的返回值缩放 StateT

haskell - 如何从 Haskell Stack 构建中编译可执行文件?

haskell - aeson 中的 FromJSON1 和 ToJSON1 是做什么用的?

haskell - 推断类型相等的 if 和 else 的约束

haskell - 类型级列表的行多态相等性

c - Haskell FFI 关于双指针参数的问题

haskell - 请帮助我理解内部和外部单子(monad)的概念

haskell - Haskell 中数字的解释

scala - Dotty 类型类的扩展与中缀特征方法

haskell - 类型族内的多态函数