如何在Haskell中推广输入

时间:2016-06-29 06:02:38

标签: haskell

我刚刚开始学习Haskell,我使用learnyouahaskell.com作为指南,我使用ghci作为解释器。我对列表有疑问。在网站上,他们指定功能:

boomBangs xs = [ if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x]

这仅适用于列表。而

boomBangs x = [ if x < 10 then "BOOM!" else "BANG!" | odd x]

仅适用于单个输入,即

boomBangs 21
boomBangs 7

有没有办法写这个语句,所以无论我是否放

boomBangs [2,5,6,7,1]

boomBangs 7

不需要if语句?

3 个答案:

答案 0 :(得分:5)

通常,Haskell不允许您随意使用多个不同的实现重载相同的函数名。有一些编程语言可以让你这样做; Haskell不是其中之一。

通常,如果您希望相同的函数针对不同类型的参数(或不同的返回类型)执行不同的操作,则使用类型类。但是,即使这样也不允许你只是任意拥有不同数量或类型的参数;必须有一个模式。

我意识到这只是为了实验目的,但我是dfeuer的评论:boomBangs应该意味着什么?什么参数类型有意义?好吧,显然在这种情况下boomBangs是一个简单的示例函数,除了作为示例函数之外,对于任何事情都没有多大意义。 (我不确定你是否已经进入了教程的类型类部分。)

请注意,正如所写,boomBangs 已经多态:它适用于任何类型的整数。它适用于带符号的8位整数,无符号8位整数,带符号的16位整数,无符号16位整数,任意精度整数......所以它适用于相当多的东西。

使列表和非列表工作不是这个函数的非常自然的概括。 (毕竟,这是热潮 - s 。)可能有意义的是将其概括为适用于其他可折叠对象(例如,列表,MaybeEither e)。它可能也适用于任何monad(例如,它似乎稍微调整一下这可能适用于有状态计算或解析器或I / O操作)。但同样,我还不知道是否已经在教程中引入了这些概念中的任何一个。

答案 1 :(得分:5)

是。以不同方式命名您的第二个函数:boomBang。然后写下boomBangs [2,5,6,7,1]boomBang 7 - 不需要if

编写代码应该简单而自然,不要让自己变得比以前更难。

现在你有了

boomBangs xs = [b | x <- xs, b <- boomBang x]

删除代码重复,这通常是未充分探索的问题空间的标志。

答案 2 :(得分:2)

您可以使用类型类为不同类型实现不同的行为。例如:

class BoomBang a where
    boomBang :: a -> [String]

instance BoomBang Integer where
    boomBang x = [if x < 10 then "BOOM" else "BANG" | odd x]

instance BoomBang a => BoomBang [a] where
    boomBang xs = xs >>= boomBang

在ghci:

> boomBang 7
["BOOM"]
> boomBang [2,5,6,7,1]
["BOOM","BOOM","BOOM"]