如何用putStr Haskell打印2个元素?

Tha*_*tos 5 haskell console-application

我是Haskell的新手,我想知道如何在Haskell中打印两个函数的结果,我会在c ++中做的事情如下:

cout << f() << g();
Run Code Online (Sandbox Code Playgroud)

或者在c#中:

Console.WriteLine(f() + " " + g());
Run Code Online (Sandbox Code Playgroud)

在Haskell中,我尝试了类似的东西

main =
    --putStr ( show $ square 3 )
    putStr ( show $ fibSeries 12 ) 

square :: Int -> Int
square x = x * x

fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)

fibSeries :: Int -> [Int]
fibSeries x = map fib [0..x]
Run Code Online (Sandbox Code Playgroud)

但我不得不评论第一个命令,因为它给了我一个编译时错误.

错误是:

src\Main.hs:21:5:
    Couldn't match expected type `(String -> IO ()) -> String -> t0'
                with actual type `IO ()'
    The function `putStr' is applied to three arguments,
    but its type `String -> IO ()' has only one
    In the expression:
      putStr (show $ square 3) putStr (show $ fibSeries 12)
    In an equation for `main':
        main = putStr (show $ square 3) putStr (show $ fibSeries 12)
Run Code Online (Sandbox Code Playgroud)

lef*_*out 14

tl; dr你真是太近了!

main = do
    putStr ( show $ square 3 )
    putStr ( show $ fibSeries 12 )
Run Code Online (Sandbox Code Playgroud)

请注意,这不会放入任何空格,您可能希望插入putStr " ".


这是正在发生的事情:Haskell的主要部分,纯粹的功能语言,没有任何"计算/行动的顺序".如果用类似的语句写两行print 5,它们只被解析为一行,即

print 5 print 5
Run Code Online (Sandbox Code Playgroud)

这意味着以下内容:print是一个函数,它的参数5,print5,并且返回的类型main(一个IO动作).所以类型需要类似

type PrintType = Int -> PrintType -> Int -> IO()
Run Code Online (Sandbox Code Playgroud)

这当然是胡说八道.要告诉Haskell你实际上想要对一系列动作进行排序(你在命令式语言中一直做什么,但在函数式编程中需要更多),我们有这个很好的do符号,它可以工作很多(但并不总是很好!)就像你从命令的立场所期望的那样.

要了解它如何工作的,您需要了解monad.这些在任何体面的Haskell教程中都有解释.阅读LYAH或其他什么.


关于你的代码的进一步说明:真正顺序完成这样的打印工作没有太大意义.您只需生成包含所需信息的字符串,然后一次打印即可:

main = putStrLn $ show (square 3) ++ " " ++ show (fibSeries 12)
Run Code Online (Sandbox Code Playgroud)

或者,如果您对格式化不是很感兴趣,而只是在获取信息时,

main = print ( square 3, fibSeries 12 )
Run Code Online (Sandbox Code Playgroud)

这将导致输出(9,[0,1,1,2,3,5,8,13,21,34,55,89,144]).