【问题标题】:MultiParamTypeClasses, FunctionalDependencies, and calling ambiguous functionsMultiParamTypeClasses、FunctionalDependencies 和调用不明确的函数
【发布时间】:2013-01-04 19:30:52
【问题描述】:

有了函数依赖,我可以声明Foo类:

class Foo a b c | a -> b where
    foo1 :: a -> b -> c
    foo2 :: a -> c

当我致电foo2 时,一切正常。由于依赖关系,编译器知道要使用哪个实例。

但是如果我删除依赖来创建Foo':

class Foo' a b c where
    foo1' :: a -> b -> c
    foo2' :: a -> c

一切仍然可以正常编译,但现在每当我尝试调用 foo2' 时,GHC 都会抛出一个错误,提示无法解析要使用的实例,因为 b 不明确。

是否可以毫无错误地调用foo2'?如果是这样,怎么做?如果不是,为什么不产生编译错误?

【问题讨论】:

  • 都不应该编译,foo1foo2 的类型意味着 a 的不同类型。你的意思是a -> b -> ca -> c
  • @DanielFischer 哎呀!你是对的。现在已经修好了。
  • b 无法从foo2' 访问,因此只有在存在指定要使用的实例的直接方法时才能确定实例。可能有一些ConstraintKinds 魔法,我不知道,但我对此表示怀疑。那么,不,你永远不能打电话给foo2'。为什么它不会产生编译错误,我不确定,但我认为是编译器无法证明你永远不能明确地调用foo2'

标签: haskell typeclass functional-dependencies


【解决方案1】:

在这种情况下不可能调用foo2',因为正如 Daniel Fischer 所说,无法确定使用哪个实例。例如,如果您有:

instance Foo' Int Int Int where
    foo2' x = x

instance Foo' Int Bool Int where
    foo2' x = x + 1

这两个foo2's 具有相同的类型签名,因此无法确定调用哪一个。

解决这个问题的常用方法是使用代理:

data Proxy a = Proxy

class Foo'' a b c = where
    foo2'' :: Proxy b -> a -> c

你用哪个来选择哪个实例:

foo'' (Proxy :: Proxy Bool) 42

【讨论】:

  • 谢谢。我真的希望 ghc 会说 Foo2' 无法编译,因为它的代码永远无法运行。哦,好吧。
猜你喜欢
  • 1970-01-01
  • 2011-10-05
  • 2011-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多