假设Goo
是我的类型类,它通常被认为是 C++、Java 或 C# 等语言中的接口等价物:
class Goo goo where ham :: goo -> String
data Hoo = Hoo
instance Goo Hoo where ham _ = "Hoo!"
mustard _ = "Oh oh."
data Yoo = Yoo
instance Goo Yoo where ham _ = "Yoo!"
mustard _ = "Whew"
但我不能返回Goo
:
paak :: (Goo goo) => String -> goo
paak g = (Yoo)
-- Could not deduce (goo ~ Yoo)
-- from the context (Goo goo)
-- bound by the type signature for paak :: Goo goo => String -> goo
-- at frob.hs:13:1-14
-- `goo' is a rigid type variable bound by
-- the type signature for paak :: Goo goo => String -> goo
-- at frob.hs:13:1
-- In the expression: (Yoo)
-- In an equation for `paak': paak g = (Yoo)
我发现了这个有启发性的陈述,它解释了原因:
该类型
paak :: (Goo goo) => String -> goo
并不意味着该函数可能会返回Goo
它想要的任何内容。这意味着该函数将返回Goo
用户想要的任何内容。
(从这里的sepp2k的答案音译)
但是,我怎样才能返回或存储满足Goo
约束条件但可以是Hoo
、Yoo
、Moo
或Boo
任何其他的东西Goo
?
我是不是太纠结于自己的编程背景,需要完全不一样的思考,比如求助于类 C 的接口:
data WhewIamAGoo = WhewIamAGoo {
ham' :: String
mustard' :: String
}
paak :: String -> WhewIamAGoo
paak g = let yoo = Yoo
in WhewIamAGoo { ham' = ham yoo
mustard' = mustard ham
}
但这似乎很尴尬。
在我的具体情况下,我想这样使用Goo
:
let x = someGoo ....
in ham x ++ mustard x
即调用者不需要知道所有的Yoo
s和诸如此类的东西。
编辑:澄清:我正在寻找Haskell程序员在这种情况下的方式。您将如何以惯用的方式处理它?