所以我需要一些帮助,或者至少需要一个正确的方向!我是Haskell的新手,但我熟悉C#和PHP。
我正在尝试创建一个允许输入3个参数的FizzBuzz函数。我理解FizzBuzz的一般概念,但我正在尝试创建一个允许你将第一个除数,第二个除数和最后一个参数作为上限的函数。我正在努力理解的部分是如何将输入值分配给函数中的变量。
我发现了不同的教程,展示了如何在Haskell中执行常规的FizzBuzz。
所以我的主要问题是:
如何为变量分配输入值?我知道如何分配类型,这将是这样的,但我不知道你将如何在函数中引用它。
fz' :: [Integer, Integer, Integer] -> Integer -> Integer -> Integer
从我在网上看到的,最好将功能分开,而不是让一个大功能来执行所有操作。话虽如此,最好是:
一个。一个函数接收输入值并为它们分配变量,然后调用单独的函数?
湾在单独的函数中,设置范围然后执行divideBy
或mod
以检查值x
是否可被[1..z]
print fizz整除,如果x
和{如果y
可以被[1..z]
打印嗡嗡声,那么y
打印fizzbuzz会导致{1}}失效吗?使用[1..z]
条款或where
是否更好?
℃。实现范围值的单独函数和case
?
任何想法,提示,帮助?
答案 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)