Haskell函数重复

时间:2015-09-25 06:45:00

标签: haskell

如果蜥蜴的尾巴被切断,再说两个再生长。如果我有下面的数据类型,我将如何编写一个函数来复制多少尾巴?

data Lizard = Tail
    deriving (Eq, Show)

duplicate :: Lizard -> Lizard
duplicate Tail?? = ???

所以输入

> duplicate Tail

应该给出

> Tail Tail

2 个答案:

答案 0 :(得分:7)

您想要的结果Tail Tail不再是蜥蜴了。实际上Tail Tail根本不是有效值。此外,你的函数duplicate不能做太多,因为它需要一个蜥蜴并返回一个蜥蜴,唯一可能的蜥蜴是Tail

如果你想要Lizards有多个Tails,你需要在Lizard数据类型中反映这一点,例如:如

data Tail = Tail deriving (Eq, Show)
data Lizard = Lizard [Tail] deriving (Eq, Show)

duplicate :: Lizard -> Lizard
duplicate (Lizard ts) = Lizard (ts++ts)

result = duplicate (Lizard [Tail])

这会给你

*Main> result
Lizard [Tail,Tail]

或申请两次

*Main> duplicate result
Lizard [Tail,Tail,Tail,Tail]

答案 1 :(得分:4)

使用Tail Tail的方式不适用于数据类型data Lizard = Tail,因为您定义的Tail是一个不带参数的构造函数。

突变重复者

如果要为每个尾部使用构造函数,可以执行以下操作:

data Lizard = Mutant Lizard Lizard | Tail

duplicate :: Lizard -> Lizard
duplicate l = Mutant l l

然后duplicate Tail会给Mutant Tail Tail。复制会产生Mutant (Mutant Tail Tail) (Mutant Tail Tail)

尾巴列表

如果它不必全部用数据编码,但使用值也可以,你可以这样做:

data Tail = Tail
data Lizard = LizMonster [Tail] | Lizard Tail

duplicate :: Lizard -> Lizard
duplicate (Lizard t) = LizMonster [t,t]
duplicate (LizMonster ts) = LizMonster (ts ++ ts)

你也可以说一个尾巴的Lizard与一个尾巴的怪物没那么不同,并且对你的所有情况都使用Lizard [Tail]。 (那么你可能想要定义类似oneTail = Lizard [Tail]的东西,因为使用单尾的列表可能有点不直观。)

从尾巴到底部

如果您不仅对重复感兴趣,我们可以定义一个与尾巴列表非常相似的蜥蜴。这将使您的输出更接近您正在寻找的内容:

data Lizard = Tail Lizard | Bottom deriving (Show)

noTail :: Lizard
noTail = Bottom

oneTail :: Lizard
oneTail = Tail Bottom

duplicate :: Lizard -> Lizard
duplicate (Tail t) = Tail . Tail $ duplicate t
duplicate Bottom = Bottom

-- Additional benefit: we can make siamese lizards
siamese :: Lizard -> Lizard -> Lizard
siamese (Tail t1) t = Tail $ siamese t1 t
siamese Bottom t = t

如果我们检查一下GHCi的显示效果,那么它非常接近你想要的东西:

duplicate oneTail
-- gives Tail (Tail Bottom)

我们可以做更多花哨的事情:

siamese (oneTail) (duplicate oneTail)
-- gives Tail (Tail (Tail Bottom))

可以说,如果你不断切断蜥蜴的尾巴,你可能会从第一个建议中获得更像树状结构的东西。