我正在写一些我认为显然是正确的代码,但似乎GHC并不这么认为:
class Convert a b where
convert :: a -> b
class (Convert a b, Convert b c) => F a b c where
f :: a -> c
f = f2 . f1
where f2 = convert :: b -> c
f1 = convert :: a -> b
Run Code Online (Sandbox Code Playgroud)
上面的代码给出了这样的错误信息,所以我想知道GHC在尝试推断出合适的类型时遇到了什么困难,或者我是否必须提供GHC更多的类型信息?
Main.hs:53:18:
Could not deduce (Convert b2 c2) ac)
bound by the class declaration for ‘F’ at Main.hs:(50,1)-(54,34)
Possible fix:
add (Convert b2 c2) to the context of
an expression type signature: b2 -> c2
In the expression: convert :: b -> c
In an equation for ‘f2’: f2 = convert :: b -> where
f2 = convert :: b -> c
f1 = convert :: a -> b
Main.hs:54:18:
Could not deduce (Convert a2 b2) arising from a use of ‘convert’
from the context (F a b c)
bound by Possible fix:
add (Convert a2 b2) to the context of
an expression type signature: a2 -> b2
In the expression: convert :: a -> b
In an equation for ‘f1’: f1 = convert :: a -> b
In an equation for ‘f’:
f = f2 . f1
where
f2 = convert :: b -> c
f1 = convert :: a -> b
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)
无论f1和f2使用b,但是这是免费的(不受限的f).怎么ghci判断b?
您可以使用ScopedTypeVariables到"链接"的b类型上f1,并f2与b上class约束
{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
class Convert a b where
convert :: a ? b
class (Convert a b, Convert b c) ? F a b c | a c ? b where -- #1
f :: a ? c
f = f2 . f1
where f2 = convert :: ? b . F a b c ? b ? c -- #2
f1 = convert :: ? b . F a b c ? a ? b -- #3
instance Convert Int String where
convert = show
instance Convert String Double where
convert = read
instance F Int String Double where
Run Code Online (Sandbox Code Playgroud)
现在
> f (34 :: Int) :: Double
34.0
Run Code Online (Sandbox Code Playgroud)
没有#1上ScopedTypeVariables的b类型名称,#2和#3都是不同的(#2和#3推断相同f2 . f1).与ScopedTypeVariables所有(#1,#2和#3)是相同的类型.
另一方面,FunctionalDependencies需要b从两个给定中选择a,c因为f没有关于它的信息.
最后,看看到@leftaroundabout响应,如果可以的话,看起来更好指定b的类型f使用幻象类型约束.
(相关问题如何在两个分离的表达式之间调和/约束类型)