Dul*_*gon 0 haskell types typeclass ghc
我有这种类型.但它无法推断出从goalequals isGoal的第一个变量类型返回的类型.如何解决这个问题?
{-# LANGUAGE TypeFamilies, FlexibleContexts #-}
class Problem p where
type State p :: *
data Action p :: *
goal :: Eq (State p) => State p
goal = undefined
isGoal :: Eq (State p) => State p -> Bool
isGoal s = s == goal
Run Code Online (Sandbox Code Playgroud)
结束这样做
class Problem p where
type State p :: *
data Action p :: *
goal :: p -> State p
goal = undefined
isGoal :: Eq (State p) => p -> State p -> Bool
isGoal p s = s == goal p
Run Code Online (Sandbox Code Playgroud)
提示就在错误消息中:
注意:'状态'是一种类型函数,可能不是单射的
这意味着什么:内射函数 f是一个函数,其中从f(x)= f(y)得到x = y.现在,我们在这里谈论类型级别,所以如果State是单独的,那么它将遵循State p ~ State q这一点p ~ q.
在s == goal中,编译器知道它需要结合goal使用s(因为==总是比较相同类型的值),所以我们有它:
s :: State p
goal :: State q
State p ~ State q
Run Code Online (Sandbox Code Playgroud)
但因为State是不是单射,编译器不能推断p ~ q,即我们只谈论型类的一个实例.
为什么不?好吧,你可以想出:
instance Problem Int where
type State Int = Bool
goal = True
instance Problem Double where
type State Double = Bool
goal = False
Run Code Online (Sandbox Code Playgroud)
现在我们有State Int ~ State Double.然而,显然Int并Double是不一样的类型,它们定义goal在矛盾的方式.
"如何解决这个问题" - 好吧,你需要重新设计课程.
您可以使用
class Problem p where
data State p :: *
Run Code Online (Sandbox Code Playgroud)
在这种情况下,State 是单射的,因为每个实例化都需要被硬化为单个instance Problem.
如果您需要能够在State其他地方定义实际类型,则需要为编译器提供p应该用于的明确提示goal.通常的解决方案是代理或 - 首选的IMO 标记值:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Tagged
class Problem p where
type State p :: *
goal :: Eq (State p) => Tagged p (State p)
goal = Tagged undefined
isGoal :: Eq (State p) => Tagged p (State p) -> Bool
isGoal = isGoalDef
isGoalDef :: forall p . Eq (State p) => Tagged p (State p) -> Bool
isGoalDef (Tagged s) = s == g
where (Tagged g) = goal :: Tagged p (State p)
Run Code Online (Sandbox Code Playgroud)