名称参数化数据类型

时间:2014-03-17 02:03:59

标签: haskell

我正在学习(再次)haskell,我有以下代码:

import qualified Data.Map as Map

data Union = Union
    {
        father :: Int,
        mother :: Int,
        offspring :: [Int]
    }
    deriving Show

data Person = Person
    {
        uid :: Int,
        name :: String,
        parentUnion :: Maybe Union,
        unions :: [Union]
    }
    deriving Show

family :: Map.Map Int Person
family = Map.fromList []

addPerson :: (Map.Map Int Person) -> Person -> (Map.Map Int Person)
addPerson family person
    | Map.member puid family = error "Repeated id"
    | otherwise = Map.insert puid person family
    where puid = uid person

现在有了更多功能,我将拥有相当多的Map.Map Int Person类型。有没有办法定义类型Family,它与Map.Map Int Person相同,所以我可以拼写:

addPerson :: Family -> Person -> Family

我天真的做法:

data Family = Map.Map Int Person

给了我一个很好的错误:

Qualified constructor in data type declaration

1 个答案:

答案 0 :(得分:3)

是。创建"输入同义词"这样,只需使用type代替data

type Family = Map.Map Int Person

这使得Family 完全与写出Map.Map Int Person相同。实际上,错误消息有时会写出完整版本而不是同义词,因此请为此做好准备。

另一种选择是使用newtype

newtype Family = Family (Map.Map Int Person)

不同之处在于,newtype版本与名称一样,是 new 类型:它与Map.Map Int Person不直接兼容。如果您尝试使用另一个预期的那个,您将收到错误。这可能对您的示例不太有用,但可用于编码类型中的其他不变量。

newtype版本与data构造几乎相同:

data Family = Family (Map.Map Int Person)

它还引入了一个新的构造函数Family,它只接受一个参数。但是,与普通数据类型不同,它仅存在于编译时; FamilyMap.Map Int Person的运行时表示仍然完全相同。