Haskell 类依赖

标签 haskell typeclass

以下代码无法编译:

class Foo f where
  getInt :: f -> Int

class Bar b where
  getFooFromBar :: Foo f => b -> f

someFunction :: Bar b => b -> Int
someFunction bar = getInt $ getFooFromBar bar

错误是无法从上下文 (Bar b) 中使用“getInt”来推断 (Foo f)

我知道我可以通过更改 Bar 的类来修复错误,如下所示:

class Foo f => Bar f b where
  getFooFromBar :: b -> f

但我更希望不必将 f 添加到 Bar 的所有实例签名中。

有没有办法通过仅在 getFooFromBar 签名而不是整个类上保留 Foo f 约束来实现此目的?

最佳答案

But I would prefer if I didnt have to add f to all the instance signatures of Bar.

从技术上讲,您不需要这样做来编译示例。您可以使用类型注释来指定在 someFunction 中使用哪个 Foo 实例,从而解决不明确的类型变量错误。但是,您有一个更深层次的问题:

class Foo f where
  getInt :: f -> Int

class Bar b where
  getFooFromBar :: Foo f => b -> f

也就是说,出于所有实际目的,这是不可能的。 getFooFromBar 的类型表明您可以使用它来生成具有 Foo 实例的 any 类型 f 的结果>。但是如何为任何 f 实现这个值呢?定义 getFooFromBar 时到达任何特定实例是没有用的,因为您将得到的只是 Couldn't match type 'f' with 'Blah' 类型错误。对此问题的直接解决方案是您在问题中出于不同原因建议的解决方案:指定要通过 Bar 实例使用的 Foo 实例。您可能会发现使用类型系列比使用多参数类型类更好:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}

class Foo f where
  getInt :: f -> Int

class Foo (FooBar b) => Bar b where
  type FooBar b :: *
  getFooFromBar :: b -> FooBar b

instance Foo Char where
   getInt = const 99

instance Bar Char where
  type FooBar Char = Char
  getFooFromBar = const 'a'

someFunction :: Bar b => b -> Int
someFunction = getInt . getFooFromBar
GHCi> someFunction 'z'
99 

关于Haskell 类依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40414449/

相关文章:

haskell - 通用字符串类型类的默认类型

performance - 编写无限列表以跳过 p 的每个因子?

Haskell 模式匹配向量

haskell - 下面的函数尾调用优化了吗?

bash - 对于查看 .tgz 文件中的源文件有什么建议吗?

haskell - 定义部分应用的类型类

haskell - Rust 中具有超特征的有界特征参数

haskell - 'many' 类型类中的“some”和 'Alternative' 函数

typeclass - 为什么定义 Choice 实例失败且值未知?

scala - 召唤辅助以获得更高种类的类型,而不引用原始类型