首页 > 解决方案 > 编写基本的 haskell 函数,获取 Int x 并在 [1..x] 上执行函数

问题描述

我正在练习一些haskell,并且在其他语言中遇到了一些非常基本的问题。

我希望我的函数接受一个 int 并返回一个字符串

oddOnly :: Int -> String

我想打印该函数的输出

print (oddOnly 20)

例如,我希望此函数打印 1-20 的所有奇数

"1 3 5 7 9 11 13 15 17 19"

我的函数显然只打印最终数字,因为我没有遍历这些数字的列表。我怎么做?

oddOnly x
    | x < 0 = error "neg"
    | x == 0 = "0"
    | mod x 2 /= 0 = show x

标签: listfunctionhaskell

解决方案


在 Haskell 中实现迭代的最基本方法是递归。Willem 试图向您展示一些更奇特的方式,但对于某些人(包括我自己)来说,很高兴看到它首先完成了基本方式。

一串奇数,比如"1 3 5 7 ...",是一个奇数"1"后面跟着一串奇数"3 5 7 ..."(它本身就是一个奇数,"3"后面跟着一串奇数,等等)。因此,如果我们已经知道如何制作一串奇数,我们可以在它的前面放一个奇数,以制作一个稍长的奇数串。这就是问题的递归结构。这是一个尝试:

oddOnly :: Int -> String
oddOnly x
  | x < 0 = error "neg"
  | x == 0 = "0"
  | mod x 2 /= 0 = show x ++ " " ++ oddOnly (x + 2)

如果我们尝试这个,我们会得到一些令人惊讶的东西:

ghci> oddOnly 1
"1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 ...

(你的屏幕会很快被奇数填满)

我们已经构建了一个无限长的奇数串(Haskell 很乐意让我们这样做:-)。我们只需要终止它——也就是说,如果参数太大,oddOnly现在不需要调用它自己。

oddOnly :: Int -> String
oddOnly x
  | x < 0 = error "neg"
  | x == 0 = "0"
  | x >= 20 = ""
  | mod x 2 /= 0 = show x ++ " " ++ oddOnly (x + 2)

我们拥有我们正在寻找的东西。了解它是如何工作的?

看看您是否可以修改此代码以将正确的端点作为参数。也许也可以将步骤(此处为 2)作为参数,这样您就可以获得例如"1 4 7 10". 您能否改为返回一个列表,然后编写一个单独的函数将它们转换为字符串joinList :: [Int] -> String (这是很好的关注点分离)?


推荐阅读