haskell - 如何使组合数据构造函数成为类的实例?

标签 haskell

我声明了以下数据类型

data Poly a = Poly [a]

还有一个类:

class Polynom p where
  substitute :: p a -> a -> a
  compose :: p a -> p a -> p a

我可以使数据类型成为类的一个实例:

instance Polynom Poly where
  substitute = ...
  compose = ...

我还希望 PolyRatio 是同一类的实例;我尝试了很多语法和语言扩展,但都不起作用;像这样的事情:

instance Polynom (Ratio . Poly) where ...
-- error: cannot use (.) there

instance Poly p => Polynom (Ratio (p _)) where ...
-- error: no wildcards allowed

type X a = Ratio (Poly x)
instance Polynom X where ...
-- error: X needs another param

instance Polynom (* -> Ratio (Poly *)) where ...
-- error: wrong kind

我的目标是能够让 substitutecomposeRatio (Poly *) 上工作;例如:

rf1 = Poly [1,2,3] % Poly [4,5,6] :: Ratio (Poly Int)
rf2 = Poly [0,1] % Poly [1,0] :: Ratio (Poly Int)
rf = rf1 `compose` rf2 :: Ratio (Poly Int)
result = substitute rf 10 :: Int

这在 Haskell 中甚至可能吗?如果是这样,我在这里缺少什么语法或语言扩展?

更新

我使用 TypeFamilies 解决了这个问题;正如@leftaroundabout 建议的那样。工作类实例如下所示*:

instance Integral a => Polynom (Ratio (Poly a)) where
  type Domain (Ratio (Poly a)) = Ratio a
  substitute (n :% d) x = substitute ((%1) <$> n) x
                        / substitute ((%1) <$> d) x
  compose (n :% d) = substitute ((pure <$> n) % (pure <$> d))

*(我实际上也改了不好的名字;但为了避免混淆,把它们放在这里了)

最佳答案

首先……如果你想要那个实例,那么这个类的名字是错误的;两个多项式的商不是多项式。

其次,您甚至不能像类那样拥有实际多项式的实例,您至少需要 Num 约束。

class Polynom p where
  substitute :: Num a => p a -> a -> a
  compose :: Num a => p a -> p a -> p a

就是说,就 Haskell 而言,这里没有太多障碍。

. 显然不能在类型级别使用,但是有 Compose这是一种等效的东西。

data Compose f g a = Compose { getCompose :: f (g a) }

这意味着用于组合仿函数,Ratio 不是,但是我认为没有理由不只是用它来组合任意 Type -> 输入 内容。

instance Polynom (Compose Ratio Poly) where
  substitute (r%d) = substitute r / substitute d

...此时您会发现 Num 约束还不够。不过,在 Polynomial 类中要求 Fractional 有点傻。

我建议您采用完全不同的方法。你可以使用像这样的类

{-# LANGUAGE TypeFamilies #-}

import Data.Kind (Type)

class Endofunction f where
  type Domain f :: Type
  evaluate :: f -> Domain f -> Domain f
  compose :: f -> f -> f

然后实例是

instance Num a => Endofunction (Poly a) where
  type Domain (Poly a) = a
  ...

并且,现在不需要 Compose

instance Fractional a => Endofunction (Ratio (Poly a)) where
  type Domain (Ratio (Poly a)) = a
  ...

我怀疑您实际上可以将其视为介于某些两个类别之间的仿函数,但它肯定不是 Hask 内仿函数。

关于haskell - 如何使组合数据构造函数成为类的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69621885/

相关文章:

scala - 为什么 Haskell 不需要蹦床?

authentication - yesod - 密码保护登台站点

haskell - 如何使 Haskell 中的 null 数据构造函数为 null 返回 True

函数上的 PostgreSQL-simple `execute` 失败并显示 "execute resulted in Col 1-column result"

haskell - 在 Scotty 服务器中 fork 新线程

algorithm - 我怎样才能加速这个图算法?

haskell - Aeson 解析为多个构造函数

haskell - 由于缩进而调试显式字符

Haskell 向量类型类 : Function of [a] -> [a] -> a

haskell - `getNumberOfProcessors` 与 cabal-install 停止联动的多重定义