我正在尝试解决功能依赖性问题,但我自己一事无成。在论文《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
要选择,它必须独立确定a
和b
,然后再去检查实例是否存在。通过函数依赖,我们可以减少这种搜索。当我们做类似的事情
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
。即使我们只为 String
和 Char
编写一个实例,我们也必须假设有人可能/将会在稍后添加另一个实例。如果没有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/