程序麻烦

时间:2014-03-30 15:53:53

标签: haskell

所以我想在Haskell中创建一个程序,该程序通过从1到n的列表,每次出现可以除以3或7文本的数字,并且每当一个数字可以除以3和7它显示了一条短信。

这是我编写的代码,但我遇到了错误:

fuction' :: Int -> [Int]
fuction' n = take n [1..]
    | (n `mod` 3) && (n `mod` 7 == 0) = error "BoomBANG!"
    | n `mod` 3 == 0 = error " boom"
    | n `mod` 7 == 0 = error " bang"

main = do
putStrLn ("a=")
a <- readLn 
print (fuction' a)

希望有人可以告诉我我的错误在哪里。

4 个答案:

答案 0 :(得分:1)

您获得的错误可能有两个来源

a)主函数输入错误

main = do putStrLn ("a=")
          a <- readLn 
          print (fuction' a)

b)你的功能正在抛出错误

 error "..."

抛出错误,你应该期待它。 所以我猜真正的答案应该包括一些提示,以摆脱错误

fuction :: Int -> [String]
fuction n = take n [1..]
          | (n `mod` 3) && (n `mod` 7 == 0) = ..
          | n `mod` 3 == 0 = ..
          | n `mod` 7 == 0 = ..
          | otherwise = .. -- you forgot one case

main :: IO ()
main = do putStrLn ("a=")
          a <- readLn 
          mapM_ putStrLn (fuction a)

答案 1 :(得分:0)

error导致程序以消息终止。您需要程序继续运行以输出其他消息。您可以通过从fuction'返回消息来完成此操作,而不是让它尝试通过调用error来终止程序来打印它们。

我们可以将程序分解成更小的部分。我们将Data.Maybe导入catMaybes以获取import Data.Maybe ,我们将在稍后使用。

message

Maybe确定是否输出数字的消息。由于某些号码没有消息,我们会使用Just "themessage"来存储Nothingmessage :: Int -> Maybe String message n | (n `mod` 3 == 0) && (n `mod` 7 == 0) = Just "BoomBANG!" | n `mod` 3 == 0 = Just " boom" | n `mod` 7 == 0 = Just " bang" | otherwise = Nothing

messages

map message从整数列表中获取所有消息。 catMaybes计算每个数字的消息。 Nothing会从列表中删除Just,并返回messages :: [Int] -> [String] messages = catMaybes . map message 值中的内容列表。

fuction'

fuction' :: Int -> [String] fuction' n = take n . messages $ [1..] 现在返回我们想要输出的所有消息,但是还没有输出它们,为下一步保存IO

printAll

map print输出每条消息。 sequence_使操作为列表中的每条消息输出消息。 printAll :: [String] -> IO () printAll = sequence_ . map print 执行所有操作,放弃他们拥有的任何结果

main

printAll的最后一行更改为调用main = do putStrLn ("a=") a <- readLn printAll (fuction' a) 以打印所有返回的消息。

{{1}}

答案 2 :(得分:0)

正如其他人所指出的,error不是控制流,它只是针对灾难性的世界性问题。 (Haskell在编写自己的控制结构时非常灵活,所以你不需要那种东西。)

您可以使用maptranspose

解决此类问题的另一种方法是分别运行每项检查,然后transpose结果

import Data.List (transpose)

ifMultipleOf n message is 
   = [if i `mod` n == 0 then message else "" | i<-is]

asSentences = unlines . map unwords

我基本上使用transposeunwords作为一种广义的zipWith

boombang is = transpose 
   [map show is, ifMultipleOf 3 "boom" is, ifMultipleOf 7 "bang" is]

哪个给出了

ghci> boombang [1..21]
[["1","",""],["2","",""],["3","boom",""],["4","",""],["5","",""],["6","boom",""],["7","","bang"],["8","",""],["9","boom",""],["10","",""],["11","",""],["12","boom",""],["13","",""],["14","","bang"],["15","boom",""],["16","",""],["17","",""],["18","boom",""],["19","",""],["20","",""],["21","boom","bang"]]
ghci> putStrLn . asSentences $ boombang [1..21]
1  
2  
3 boom 
4  
5  
6 boom 
7  bang
8  
9 boom 
10  
11  
12 boom 
13  
14  bang
15 boom 
16  
17  
18 boom 
19  
20  
21 boom bang

答案 3 :(得分:0)

其他人已经指出了使用错误的危险。这是使用map函数解决方案的另一种尝试,并大量借用mapM_ @ AndrewC的解决方案,但将地图从IO monad中取出。如果您选择任何其他解决方案,我将解决我的解决方案。

function' :: Int -> [(Int, String)]
function' n = map (\x -> (x, compute x)) (take n [1..])
compute n
        | ((n `mod` 3 == 0) && (n `mod` 7 == 0)) =  "BoomBANG!"
        | n `mod` 3 == 0 =  " boom"
        | n `mod` 7 == 0 = " bang"
        | otherwise  = ""


main = do
  putStrLn ("a=")
  a <- readLn
  print (function' a)