haskell - 解决多参数类型类的模棱两可的实例

标签 haskell ghc

我正在开发一个专门的数值数据处理库,但遇到了一个我无法解决的错误。我认为先展示一个例子然后解释我的问题会更容易。我也为奇怪的名字道歉,出于法律目的我不得不混淆。

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances     #-}

data MyError = MyError String deriving (Eq, Show)

data MyList    = MyList [Double] deriving (Eq, Show)
data NamedList = NamedList String MyList deriving (Eq, Show)

class MyNum a b ret where
    myAdd       :: a -> b -> Either MyError ret
    myLessThan  :: a -> b -> Either MyError Bool

instance MyNum MyList Double MyList where
    myAdd (MyList xs) x = Right $ MyList $ map (+x) xs
    myLessThan (MyList xs) x = Right $ all (< x) xs

instance MyNum NamedList Double NamedList where
    myAdd (NamedList n l) x = fmap (NamedList n) $ myAdd l x
    myLessThan (NamedList n l) x = myLessThan l x

如果我尝试编译它,我会收到错误
No instance for (MyNum MyList Double ret0)
  arising from a use of `myLessThan'
The type variable `ret0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there is a potential instance available:
  instance MyNum MyList Double MyList
    -- Defined at testing_instances.hs:13:10
Possible fix:
  add an instance declaration for (MyNum MyList Double ret0)
In the expression: myLessThan l x
In an equation for `myLessThan':
    myLessThan (NamedList n l) x = myLessThan l x
In the instance declaration for `MyNum NamedList Double NamedList'

因为编译器无法确定 MyNum 的具体实例。用于MyList .它适用于 myAdd因为 MyNum 的返回类型很容易推导出来,但它无法为 myLessThan 计算出来.我想使用这个类型类,以便我可以轻松地在整个过程中添加细粒度的错误处理,并且因为我的实际代码具有 +、-、*、/、<、<=、> 和 >= 的等价物,并且我想要为 MyNum Double MyList MyList 创建一个实例, MyNum MyList MyList MyList ,以及 NamedList 的类似内容.除非有更简单的方法可以做到这一点,否则我可以拥有多态交换运算符。

但是,我无法确定要添加到 myLessThan 的类型签名。对于第二个实例,以便它可以知道要使用哪个实例。我知道一种解决方案是将算术和比较运算符拆分为两个单独的类型类,但我想尽可能避免这样做。

最佳答案

您可以使用functional dependencies指定“retab 唯一确定”。

...
{-# LANGUAGE FunctionalDependencies #-}
...
class MyNum a b ret | a b -> ret where
...

这让类型检查器知道它可以选择正确的实例定义,只知道 ab从你的论点:
myLessThan (NamedList n l) x = myLessThan l x

如果您使用相同的 a 定义其他实例,编译器现在会报错。和 b但不同的ret , 如
instance MyNum MyList Double SomeOtherType where

关于haskell - 解决多参数类型类的模棱两可的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18453645/

相关文章:

haskell - ScopedTypeVariables 不会将类型变量带入作用域

haskell - 如何在 GHC 中仅为旧版本定义功能?

haskell - GHC 拆分性能

haskell - 是否可以将 HOAS 函数转换为连续传递样式?

haskell - 在 GHCI 中时正确的行为,在文件中时键入错误

Haskell 无点编译类型

haskell - 如何将数据类型带入值(value)级别?

haskell - GHC垃圾收集器对于大对象有什么特殊的优化吗?

algorithm - 具有键值的Haskell二叉树

haskell - 我将 ghc 更新到新版本,如何自动重新安装所有 cabal 软件包?