RCI*_*CIX 11 haskell pretty-print fizzbuzz
我是哈斯克尔的新手,我读完并消化了" 了解你是一件好事",并尝试了一些事情.对于我的第一个项目,我想尝试经典:FizzBuzz.所以我想出了以下代码:
import System.IO
fizzBuzz :: (Integral a) => a -> String
fizzBuzz num
| fizz && buzz = "FizzBuzz"
| fizz = "Fizz"
| buzz = "Buzz"
| otherwise = show num
where fizz = num `mod` 3 == 0
buzz = num `mod` 5 == 0
main = print $ map fizzBuzz [1..100]
Run Code Online (Sandbox Code Playgroud)
工作得很好,除了我有一个很难读的相当密集的列表.所以我尝试了这个主要功能:
main = map putStrLn $ map fizzBuzz [1..100]
Run Code Online (Sandbox Code Playgroud)
这给了我错误Couldn't match expected type 'IO t' against inferred type '[IO ()]'
.我尝试了六件事,似乎没有任何帮助.做我想做的事情的正确方法是什么?
eph*_*ent 26
map :: (a -> b) -> [a] -> [b]
putStrLn :: Show a => a -> IO ()
map putStrLn :: Show a => [a] -> [IO ()]
Run Code Online (Sandbox Code Playgroud)
你有一个IO ()
行动清单.
main :: IO ()
Run Code Online (Sandbox Code Playgroud)
您需要将它们合并为一个IO ()
操作.
您要做的是IO ()
按顺序/sequence_执行每个操作:
sequence :: Monad m => [m a] -> m [a]
sequence_ :: Monad m => [m a] -> m ()
Run Code Online (Sandbox Code Playgroud)
为方便起见,mapM/mapM_将在列表上映射函数并对生成的monadic结果进行排序.
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM_ :: Monad m => (a -> m b) -> [a] -> m ()
Run Code Online (Sandbox Code Playgroud)
所以你的固定代码看起来像这样:
main = mapM_ putStrLn $ map fizzBuzz [1..100]
Run Code Online (Sandbox Code Playgroud)
虽然我可能会这样写:
main = mapM_ (putStrLn . fizzBuzz) [1..100]
Run Code Online (Sandbox Code Playgroud)
甚至这个:
main = putStr $ unlines $ map fizzBuzz [1..100]
Run Code Online (Sandbox Code Playgroud)
让我们写自己的sequence
.我们想要它做什么?
sequence [] = return []
sequence (m:ms) = do
x <- m
xs <- sequence ms
return $ x:xs
Run Code Online (Sandbox Code Playgroud)
IO
monad,这意味着执行)第一个结果.sequence
列表的其余部分; 绑定结果列表.GHC的图书馆使用更类似的东西,foldr (liftM2 (:)) (return [])
但更难以向新手解释; 现在,请接受我的说法,他们是等同的.
sequence_
更容易,因为它不会打扰跟踪结果.GHC的库实现它sequence_ ms = foldr (>>) (return ()) ms
.我们只是扩展定义foldr
:
sequence [a, b, c, d]
= foldr (>>) (return ()) [a, b, c, d]
= a >> (b >> (c >> (d >> return ())))
Run Code Online (Sandbox Code Playgroud)
换句话说,"做a
,丢弃结果;做b
;丢弃结果,......最后,返回()
".
mapM f xs = sequence $ map f xs
mapM_ f xs = sequence_ $ map f xs
Run Code Online (Sandbox Code Playgroud)
另一方面,您甚至不需要使用备用unlines
解决方案来了解monad .
怎么unlines
办?好吧,lines "a\nb\nc\nd\n" = ["a", "b", "c", "d"]
当然unlines ["a", "b", "c", "d"] = "a\nb\nc\nd\n"
.
unlines $ map fizzBuzz [1..100]
= unlines ["1", "2", "Fizz", ..]
= "1\n2\nFizz\n..."
然后关闭它putStr
.由于Haskell的懒惰的魔力,完整的字符串永远不需要在内存中构建,所以这将愉快地去[1..1000000]
或更高:)
归档时间: |
|
查看次数: |
2803 次 |
最近记录: |