'MyModule.myTypeclassFunction'的多个声明

时间:2011-01-25 21:50:03

标签: haskell

Main.hs中的

class A aable where
    getName :: aable → String

class B bable where
    getName :: bable → String

使用Leksah / ghc

返回此编译错误
src\Main.hs:23:4:
    Multiple declarations of `Main.getName'
    Declared at: src\Main.hs:20:4
                 src\Main.hs:23:4

我需要两者都能够返回一个名称,在两种情况下都有不同的含义。 我应该在两个不同的模块中声明A类和B类吗?

2 个答案:

答案 0 :(得分:3)

Kneejerk反应:使用Show。阅读更好,我看到你想要的是语义上不同的(尽管类型签名相同)。为什么不使用不同的名字?也许descriptionAdescriptionB?在不同的模块中声明它们可以解决编译错误,但是(1)你仍然有两个不同的东西具有相同的名称,(2)每当你导入两个模块(不合格)时,你都会得到同样的错误。

答案 1 :(得分:3)

如果你有不同的数据类型,但行为不同,但有些相同(如同,有相同的方法但不同的实现),那么它就是Haskell类来拯救!

data A = A { nameA :: String } deriving (Show, Eq)
data B = B { nameB :: String } deriving (Show, Eq)

class Named a where
    getName :: a -> String

instance Named A where
    getName = nameA

instance Named B where
    getName = nameB

ghci> getName $ A "foo"
"foo"
ghci> getName $ B "bar"
"bar"

(如果你还没有看过记录语法,那就是good explanation at LYAH

你甚至可以更加一般。

{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
-- The above line should be at the top of your file

-- add this to the file too (anywhere)
instance (Show a) => Named a where
    getName = show

ghci> getName 3
"3"
ghci> show 3
"3"
ghci> getName $ A "foo"
"foo"
ghci> show $ A "foo"
"A {nameA = \"foo\"}"

如果同时保留Instance (Show a) => Named ainstance Named A,则只需在此示例中使用OverlappingInstances语言编译指示,因为我通过派生A Show实例A 。谨慎而谨慎地使用语言编译语。

我提供了B(Show a)数据用于说明目的,但{{1}}实例说明了如何在类中轻松完成此操作。