一些背景知识:
我是一名业余程序员,几个月前,在学习了一段时间的 Mathematica 编程(我的第一语言)之后,我利用业余时间学习了 Haskell。我目前正在阅读 Will Kurt 所著的第二本 Haskell 书,但要让自己对 Haskell 代码感到满意还有很长的路要走。到目前为止,Codeabbey 一直是我进行实验和学习的平台。
我编写了一段代码来生成给定数字的排列,处理可能的重复数字,因此对于 588,它将在内部生成 588、858 和 885。
但是,因为我想扩展到相当大的输入数字(认为可能甚至有一百位数字长),所以我不想输出整个列表,然后对其执行计算,而是当场检查生成的每个数字对于某个属性,如果它有,那么我们就有一个获胜者,该数字作为输出返回,并且无需遍历庞大列表的其余部分。如果不幸的是没有找到所需的数字,并且我们未能成功地完成所有可能的排列,它会输出“0”。
我还选择将其设为命令行程序,通过 gnu parallel 向其提供值,以加快工作速度。
所以这是代码
import System.Environment
import Data.List
toDigits :: Integer -> [Integer]
toDigits n = map (\n -> read [n]) (show n)
fromDigits :: Integral a => [a] -> Integer
fromDigits list = fromDigitsHelperFunction list 0
fromDigitsHelperFunction :: Integral a => [a] -> Integer -> Integer
fromDigitsHelperFunction [] acc = acc
fromDigitsHelperFunction (x:[]) acc = (fromIntegral x) + acc …Run Code Online (Sandbox Code Playgroud) 您可能已经猜到了,完全是初学者。我已经完成了“Learn you a Haskell”,但我仍然在基础知识上挣扎。
我正在看这个线程 用 Haskell 将一个数字拆分成它的数字 ,这个函数开始变得有意义了
digits :: Integer -> [Int]
digits n = map (\x -> read [x] :: Int) (show n)
Run Code Online (Sandbox Code Playgroud)
丹尼尔问。
我知道 show 将我的输入数字作为字符串或字符列表返回,然后我可以使用 map 逐个修改元素。因此,每个“x”,作为一个字符,被匿名函数选择并读取为一个整数,新列表由 map 组成,包含所有读取的整数。那不read [x]应该read x吗?为什么列表中的每个读取 Char 都需要作为它自己的单例列表返回?在我看来,这种调用方式digits 123应该返回[[1],[2],[3]],因为 map 无论如何都会将所有内容组合到一个新列表中,而不是[1,2,3]像它正确的那样。但为什么?
我有以下函数,它将递归地乘以一个数字的数字,直到它达到一个数字
multResWithCounter' :: (Int, [Int],[Integer]) -> (Int, [Int],[Integer])
multResWithCounter' (counter, listOfDigits,listOfProducts)
| (length listOfDigits) <= 1 = (counter, listOfDigits, listOfProducts)
| otherwise = multResWithCounter' ((counter + 1), newListOfDigits, digitProduct:listOfProducts)
where newListOfDigits = map (\n -> read [n] :: Int) (show $ digitProduct)
digitProduct = ((product listOfDigits) :: Integer)
Run Code Online (Sandbox Code Playgroud)
这当然不能在 ghci 中编译,抱怨它无法将预期类型的 Integer 与实际类型的 Int 匹配。如果我退缩并将类型声明更改为 Int 并调用它,例如,
multResWithCounter' (0,[2,7,7,7,7,7,7,8,8,8,8,8,8,9,9],[])
Run Code Online (Sandbox Code Playgroud)
我得到
(2,[0],[0,1191706624])
Run Code Online (Sandbox Code Playgroud)
现在这个“1191706624”当然是结果
(product [2,7,7,7,7,7,7,8,8,8,8,8,8,9,9]) `mod` (maxBound :: Int)
Run Code Online (Sandbox Code Playgroud)
果然第一部分在ghci中直接运行的结果是正确的4996238671872。
那么,我怎样才能让 Haskell 给我 Integer 产品结果(无论如何我会立即转向字符串显示)?
谢谢
大家,早安!
我使用以下函数作为需要简单输入和输出的函数的合适示例。在本例中,它是一个将数字从十进制转换为二进制形式的函数,同样作为数字列表,只是因为以后方便。
我选择这样写,因为即使输入一个数字并输出一个列表,也需要另一个结构作为中间步骤,它将保存到目前为止找到的数字并保存除法的商,作为循环的下一步。不过,在输出任何内容之前,我会通过选择我感兴趣的结构部分(在本例中是第二个)来清理必要的混乱,而不是计数器或其他我已经完成的东西。(正如我提到的,这只是一个示例,在其他情况下,until使用像 (a,b,c) 这样的三元组初始化循环并不罕见,只是在最后选择其中一个,正如我认为合适的那样,使用附加功能的帮助,例如pickXof3。)
所以在那里,
dec2Bin :: Int -> [Int]
dec2Bin num = snd $ until
(\(n,l) -> n <=0) -- test
(\(n,l) -> (fst $ division n, (snd $ division n):l)) -- main function
(num,[]) -- initialization
where division a = divMod a 2
Run Code Online (Sandbox Code Playgroud)
我发现 Haskell 虽然缺少传统的 for/while 循环,但有一个类似 的函数,这非常方便,这让我想起了我熟悉的untilMathematica 的。NextWhile
过去我会写得更难看,比如两个函数,一个“辅助”函数和一个“主”函数,就像这样
dec2BinHelper :: (Int,[Int]) -> (Int,[Int])
dec2BinHelper (n,l)
| n <= 0 = (n,l)
| otherwise = dec2BinHelper …Run Code Online (Sandbox Code Playgroud) haskell ×4