5

私はHaskellを初めて使用し、Haskellで2つの関数の結果をどのように出力できるか疑問に思っています.C ++で次のようにします:

cout << f() << g();

またはC#で:

Console.WriteLine(f() + " " + g());

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]

しかし、コンパイル時にエラーが発生したため、最初のコマンドをコメントする必要がありました。

エラーは次のとおりです。

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)
4

2 に答える 2

14

tl;drあなたはとても近いです!

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

これは空白を挿入しないことに注意してください。挿入したい場合がありますputStr " "


何が起こっているのか: Haskell の主要部分である純粋関数型言語には、「計算の順序 / アクション」などというものはありません。のようなステートメントで 2 行を記述した場合print 5、それらは 1 行として解析されます。

print 5 print 5

これは次のことを意味します:printは、引数5print、およびを受け取り、 (アクション)5の型を返す関数です。したがって、タイプは次のようにする必要がありますmainIO

type PrintType = Int -> PrintType -> Int -> IO()

もちろんナンセンスです。Haskell に一連のアクション (命令型言語では常に行うが、関数型プログラミングではほとんど必要としないこと)を実際にシーケンス化したいことを伝えるために、この素​​敵なdo表記法があります。あなたが命令的な観点から期待するように。

それが実際にどのように機能するかを理解するには、モナドについて学ぶ必要があります。これらは、適切な Haskell チュートリアルで説明されています。LYAHか何かを読んでください。


コードに関するその他の注意事項: このような印刷ジョブを順番に実行しても、実際にはあまり意味がありません。必要なすべての情報を含む文字列を生成し、それを一度に出力できます。

main = putStrLn $ show (square 3) ++ " " ++ show (fibSeries 12)

または、書式設定にあまり関心がなく、情報を取得することにのみ関心がある場合は、

main = print ( square 3, fibSeries 12 )

これにより、出力が得られます(9,[0,1,1,2,3,5,8,13,21,34,55,89,144])

于 2013-06-24T09:03:32.867 に答える