假设我定义了一个多参数类型类:
当我尝试在
{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes, FlexibleContexts, FlexibleInstances #-}
class Table a b c where
decrement :: a -> a
evalutate :: a -> b -> c
然后我定义一个使用 decrement
的函数,为了简单起见:
d = decrement
当我尝试在
ghci
(版本8.6.3)中加载此内容时:• Could not deduce (Table a b0 c0)
arising from a use of ‘decrement’
from the context: Table a b c
bound by the type signature for:
d :: forall a b c. Table a b c => a -> a
at Thing.hs:13:1-28
The type variables ‘b0’, ‘c0’ are ambiguous
Relevant bindings include d :: a -> a (bound at Thing.hs:14:1)
These potential instance exist:
instance Table (DummyTable a b) a b
这让我感到困惑,因为d
的类型恰好是decrement
的类型,在类声明中有说明。
我想到了以下解决方法:
data Table a b = Table (a -> b) ((Table a b) -> (Table a b))
但是这种表示方式在符号上不太方便,而且我只是想知道为什么我首先会收到这个错误信息。
Table
无法编译。GHC 给出了一条信息,建议使用AllowAmbiguousTypes
。所以我看到你开启了它。这是个可怕的想法,GHC 不应该提到它。根据 @typedfern 的回答,功能依赖是一个更好的方法。我正在努力修复 GHC,防止它给新手做出荒谬的建议。 - AntCTypeApplications
来消除歧义,那么AllowAmbiguousTypes
就完全没问题了。我更喜欢这种方法而不是使用代理。但是,在这种特定情况下,它不是正确的解决方案,GHC 的建议也不合适。在这里,应该使用 fundeps(或类型族)。 - chiTypeApplications
的人可能已经打开了AllowAmbiguousTypes
。因此,该消息应适用于在其方法签名中犯错误的人。它应提到所有可能的方法/更正,而不是支持一个高级功能(它实际上没有命名),并保持沉默。这就像太空人接管鸡舍一样。 - AntC