haskell - Haskell 中的函数依赖

标签 haskell typeclass

我正在尝试解决功能依赖性问题,但我自己一事无成。在论文《Monad Transformers Step by Step》中,作者给出了这两个类型类的定义:

class (Monad m) => MonadError e m | m -> e where
    throwError :: e -> m a
    catchError :: m a -> (e -> m a) -> m a

class (Monad m) => MonadReader r m | m -> r where
    ask :: m r
    local :: (r -> r) -> m a -> m a

根据我在网上找到的一些资料的理解,这意味着类型变量e是由m决定的。我只是不明白那是什么意思。它是如何确定的?任何人都可以先用最少的理论阐明一些道理,然后再链接更重要的理论内容吗?

谢谢

最佳答案

当您有多参数类型类时,默认情况下,类型变量是独立考虑的。因此,当类型推断器试图找出哪个实例时

class Foo a b

要选择,它必须独立确定ab,然后再去检查实例是否存在。通过函数依赖,我们可以减少这种搜索。当我们做类似的事情

class Foo a b | a -> b

我们的意思是“看,如果您确定 a 是什么,那么就有一个唯一的 b,因此 Foo a b > 存在,所以不必费心去推断 b,只需查找实例并对其进行类型检查即可”。 这让类型推断器更加有效,并有助于在许多情况下进行推断地点。

例如,这对于返回类型多态性特别有用

class Foo a b c where
  bar :: a -> b -> c

现在无法推断

  bar (bar "foo" 'c') 1

因为我们无法确定c。即使我们只为 StringChar 编写一个实例,我们也必须假设有人可能/将会在稍后添加另一个实例。如果没有fundeps,我们就必须实际指定返回类型,这很烦人。但是我们可以写

class Foo a b c | a b -> c where
  bar :: a -> b -> c

现在很容易看出 bar "foo"'c' 的返回类型是唯一的,因此是可推断的。

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

相关文章:

scala - 参数化类与函数

haskell - Haskell 什么时候需要类型签名?

haskell - 跨类型类的模式匹配

haskell - 如何使用 pandoc API 转换多文件 LaTeX 文档?

haskell - 如何为此 GADT 编写序列化实例?

haskell - 如何在 Quickcheck 中使用修饰符(在我的情况下为正)

haskell - 为什么类型类难以实现?

haskell - Haskell 数据声明可以受类型值的限制吗

haskell - Scotty:连接池作为单子(monad)阅读器

haskell - 类型类的替代品?