无法将预期类型'r'与实际类型'Horse'

时间:2016-08-04 06:20:41

标签: haskell typeclass

我正在摆弄Haskell,但却遇到了问题。以下代码:

class HasHorses e where yieldInHorses :: (InHorses r) => e -> r
class InHorses e

data Horse = Horse String
data Stable = Stable String

instance InHorses Horse
instance HasHorses Stable where yieldInHorses e = (Horse "Buttercup")

给我以下错误:

source_file.hs:10:52: error:
    • Couldn't match expected type ‘r’ with actual type ‘Horse’
      ‘r’ is a rigid type variable bound by
        the type signature for:
          yieldInHorses :: forall r. InHorses r => Stable -> r
        at source_file.hs:10:33
    • In the expression: (Horse "Buttercup")
      In an equation for ‘yieldInHorses’:
          yieldInHorses e = (Horse "Buttercup")
      In the instance declaration for ‘HasHorses Stable’
    • Relevant bindings include
        yieldInHorses :: Stable -> r
          (bound at source_file.hs:10:33)

第10行指的是我instance HasHorses Stable where ...的行。

也许我忽略了一些事情,但我不明白为什么这应该是一个错误。实际的Type Horse满足r的约束条件,即它应该是InHorses。

' yieldInHorses'方法是对于HasHorses的东西,在它上面调用这个方法应该告诉我马(好吧,马,开头 - 这将包括很快的列表),它有。

我犯了一个简单的错误或误解了一些更基本的东西吗?

2 个答案:

答案 0 :(得分:3)

我认为您正在寻找相关类型

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}

class HasHorses e where
  type R e  :: *
  yieldInHorses :: (InHorses (R e)) => e -> R e

class InHorses e

data Horse = Horse String
data Stable = Stable String

instance InHorses Horse

instance HasHorses Stable where
  type R Stable = Horse
  yieldInHorses e = (Horse "Buttercup")

test = yieldInHorses (Stable "asd")

在我们定义HasHorses实例时,我们也定义了 相关的马类型是什么。

正如@Alexis King所提到的,yieldInHorses的签名允许 调用者确定返回类型是什么。例如,他们 可以要求:

yieldInHorses (Stable "asd") :: Int

但似乎您希望根据您定义的实例返回特定类型。

<强>更新

这是另一种为yieldInHorses删除签名的方法 需要FlexibleContexts并与GHC 8一起使用:

  yieldInHorses :: (InHorses r, r ~ R e) => e -> r

答案 1 :(得分:0)

正如上面评论中所述,(InHorses r) => e -> r的{​​{1}}类型意味着,如果给定类型为yieldInHorses的值,则可以返回值 any < / strong>类型e满足r约束。但是,该实现始终会返回特定的InHorsesr

由于示例似乎不完整(在Horse的实现中忽略Stable值),因此很难知道什么最适合您。如果yieldInHorses只能 生成Stable,那么函数依赖或类型族方法是有意义的。但是,如果Horse维护了一些可以用于生成任何Stable的状态,那么构造函数方法可能会很有用。例如,如果所有InHorses r => r都可以从InHorses

构建
String