【问题标题】:Could not deduce from the context无法从上下文推断
【发布时间】:2015-07-21 20:52:21
【问题描述】:

我有这个类型类。但它不能推断出从goal 返回的类型等于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 

最终这样做了

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

【问题讨论】:

  • 如果您能以其他方式呈现错误消息,那就太好了。来自 Windows 控制台的屏幕截图,说真的……
  • 它没有意识到您正在尝试使用同一实例中的goal
  • @leftaroundabout 从 Windows 控制台复制和粘贴很烦人,我可以理解更喜欢截屏。
  • @Ørjan Johansen 好吧,这比从 Windows 控制台屏幕截图复制和粘贴更烦人!问题是,为什么首先使用 Windows 控制台?除了完全切换到更好的操作系统外,还有 WinGHCi 的选项。
  • 截屏的最大问题是不能保证图像将始终被托管和可用。请复制粘贴!

标签: haskell types ghc typeclass


【解决方案1】:

提示就在错误消息中:

     N.B.:“State”是一个类型函数,可能不是单射的

这意味着:injective function f 是一个函数,其中 f(x) = f(y) 它遵循 x = y。现在,我们在这里讨论类型级别,所以如果 State 是单射的,那么它会从 State p ~ State q 遵循 p ~ q

s == goal 中,编译器知道它需要将goals 统一起来(因为== 总是比较相同类型的值),所以我们有了它:

s :: State p
goal :: State q
State p ~ State q

但因为State 不是单射的,编译器无法推断p ~ q,即我们只讨论类型类的单个实例。

为什么不呢?好吧,你可以想出:

instance Problem Int where
  type State Int = Bool
  goal = True

instance Problem Double where
  type State Double = Bool
  goal = False

现在我们有State Int ~ State Double。然而显然IntDouble 不是同一类型,它们以相互矛盾的方式定义goal


“如何解决这个问题”——好吧,你需要重新设计这个类。

  • 你可以使用

    class Problem p where 
      data State p :: * 
    

    在这种情况下,State 单射的,因为每个实例化都需要硬烘焙到单个 instance Problem

  • 如果您需要在其他地方定义实际的State 类型,您需要给编译器一个明确的提示,即p 应该用于goal。通常的解决方案是代理或 - 首选 IMO - tagged 值:

    {-# 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)
    

【讨论】:

    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-01
    • 2021-08-02
    • 2015-08-28
    • 2019-04-05
    • 2018-11-08
    • 1970-01-01
    相关资源
    最近更新 更多