在这里,我定义了两个类F
和O
。 F
用于多态函数f
,O
用于多态值o
。
{-# LANGUAGE MultiParamTypeClasses #-}
class F a b where
f :: a -> b
class O a where
o :: a
data K = K
data L = L
data M = M
instance O K where
o = K
instance O L where
o = L
instance F K L where
f K = L
instance F L K where
f L = K
instance F L L where
f L = L
instance F M K where
f M = K
为了方便起见,这里列出了任何一个类的可能实例:
F K L
F L K
F L L
F M K
O K
O L
现在,如果我在GHCi中输入以下内容:
f o :: K
我希望Haskell能够确定,因为最终结果必须是K
,这意味着f
的可能实例是F M K
和F L K
,但是从{{ 1}}只能是o
而不是L
,必须是M
为o
且L
为f
的情况。也就是说,没有任何其他可能性,结果应该是F L K
。但事实证明,Haskell无法解决这个问题:
K
你认为这是因为编译器不够智能,或者你认为我的表达中存在实际的歧义吗?
答案 0 :(得分:1)
o
会返回任何类型:o :: a
。
将其提供给f
会产生
:t f o
f o :: F a b => b
这意味着a
可以是任何类型。所以o
含糊不清。
f o :: K
在b
K
中f :: a -> b
F a b
个f
。
上述两种情况都会产生instance F a0 K
instance F L K
instance K M K
有两个候选人
o
O
返回instance O K
instance O L
类的任何实例。只定义了两个实例:
f o :: K
因此o
含糊不清,因为GHC
含糊不清。
我认为Route::get('password/email', ['uses' => 'Auth\PasswordController@getEmail', 'as', 'session.getEmail']);
以这种方式推断类型(仅搜索合适的实例),以便不陷入循环。但我只是开始学习它,所以我在这里错了。
有一种描述here和here (shortly)的技术可以帮助编译器推断出正确的实例。