未能与实际类型'Horse'匹配预期类型'r'
我在与Haskell一起摆弄,但正在努力解决问题。下面的代码:未能与实际类型'Horse'匹配预期类型'r'
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来说,调用这个方法应该告诉我马匹(好吧,马,开始 - 这将包括很快列表),它有。
我做了一个简单的错误还是误解了一些更基础的东西?
我认为您在寻找关联类型。
{-# 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
如上文的评论中提到,类型(InHorses r) => e -> r
的yieldInHorses
意味着如果给定值e
,它能够返回的任意值类型r
t帽子满足InHorses
约束。但是,实施始终返回特定的r
,Horse
。
由于该示例看起来不完整(在执行yieldInHorses
时Stable
的值被忽略),很难知道哪种方法最适合您。如果一个Stable
可以只有产生Horse
s,功能依赖或类型家庭方法是有道理的。然而,如果一个Stable
保持某种状态,然后可以用于生成任何InHorses r => r
,也许构造方法可能是有用的。例如,如果所有InHorses
能够被从一个String
构造:
class InHorses e where makeHorse :: String -> e
instance InHorses Horse where makeHorse s = Horse s
instance HasHorses Stable where yieldInHorses e = makeHorse "Buttercup"
类型yieldInHorses'的'实际上是'的forall河InHorses r => e - > r',这意味着*调用者可以决定*'r'应该是什么。你正在寻找的东西就像'exists'而不是'forall',虽然[它可以使用其他结构对它们进行类似的编码](https://wiki.haskell.org/ Existential_type)。然而,这是一个这样一个人为的例子,很难给出具体的建议 - 为什么你会需要像InHorses这样的类型类型呢? –
而不是'InHorses r => e - > r'只需使用'e - > Horses',其中'Horses'是一种可以正确捕捉所有想要的信息的类型,可能是[Horse]'。 – user2407038
我想知道你为什么使用类型类。你真的需要他们吗?如果一个类型类只有一个实例,那么你可能应该放弃它并直接使用plain类型。 – chi