多个输入值,范围为

时间:2015-08-12 20:08:52

标签: haskell fizzbuzz

所以我需要一些帮助,或者至少需要一个正确的方向!我是Haskell的新手,但我熟悉C#和PHP。

我正在尝试创建一个允许输入3个参数的FizzBu​​zz函数。我理解FizzBu​​zz的一般概念,但我正在尝试创建一个允许你将第一个除数,第二个除数和最后一个参数作为上限的函数。我正在努力理解的部分是如何将输入值分配给函数中的变量。

我发现了不同的教程,展示了如何在Haskell中执行常规的FizzBu​​zz。

所以我的主要问题是:

  1. 如何为变量分配输入值?我知道如何分配类型,这将是这样的,但我不知道你将如何在函数中引用它。

    fz' :: [Integer, Integer, Integer] -> Integer -> Integer -> Integer
    
  2. 从我在网上看到的,最好将功能分开,而不是让一个大功能来执行所有操作。话虽如此,最好是:

    一个。一个函数接收输入值并为它们分配变量,然后调用单独的函数?

    湾在单独的函数中,设置范围然后执行divideBymod以检查值x是否可被[1..z] print fizz整除,如果x和{如果y可以被[1..z]打印嗡嗡声,那么y打印fizzbuzz会导致{1}}失效吗?使用[1..z]条款或where是否更好?

    ℃。实现范围值的单独函数和case

  3. 任何想法,提示,帮助?

1 个答案:

答案 0 :(得分:4)

在PHP中,您可以定义一个这样的函数:

function abc($x, $y) { ... }

在Haskell中你会这样做:

abc x y = ...

如果你想添加一个类型签名:

abc :: Int -> String -> Whatever
abc x y = ...

你的广义fizz-buzz的Haskell版本可能会这样定义:

myFizzBuzz :: Int -> Int -> Int -> [String]
myFizzBuzz    div1   div2   upperBound =
  -- here `div1` is the first divisor, `div2` the second
  -- and `upperBound` is the upper bound of the range
  ...
  -- return a list of strings, e.g. ["Fizz", "Fizz", "Buzz", ... ]

请注意myFizzBuzz会返回一个字符串列表 - 它不会打印出来。要打印出来,只需使用lines加入生成的字词,然后调用putStrLn

printMyFizzBuzz div1 div2 upperBound = 
  putStrLn $ lines (myFizzBuzz div1 div2 upperBound)

这也说明了在Haskell程序中普遍存在的IO与计算的分离:您将程序结构化为主要由精简IO层包围的纯计算。在这种情况下,myFizzBuzz是您的纯函数。从控制台获取参数的完整程序可能如下所示:

main = do
  (arg1 : arg2 : arg3 : _) <- fmap words getLine  -- IO layer
  let div1 = read arg1                            -- pure core
      div2 = read arg2                            --  |
      upperBound = read arg3                      --  |
  let results = myFizzBuzz div1 div2 upperBound   -- pure core
  putStrLn $ lines results                        -- IO layer

编写纯函数的一个原因是它们往往更容易重用。

而不是在myFizzBuzz中指定上限而不是写入它来生成无限系列的“Fizz”和“Buzz”字符串:

allFizzBuzz :: Int -> Int -> [String]
allFizzBuzz div1 div2 = ...
  -- the infinite Fizz-Buzz sequence for divisors div1, div2 starting with 1

然后myFizzBuzz只是由take组成的allFizzBuzz函数:

myFizzBuzz div1 div2 upperBound = take upperBound (allFizzBuzz div1 div2)