2017-04-25 4 views
1

次のコードでは、階乗の結果を整数で表示しようとしています。私は次のエラーメッセージを受け取りました。私は何が起こったのか、そしてなぜそれが不思議です。ありがとう!if-else文でintを表示/印刷できない

factorial2 0 = 1 
factorial2 n = n * factorial2 (n-1) 

main = do putStrLn "What is 5! ?" 
     x <- readLn 
     if x == factorial2 5 
      then putStrLn "Right" 
      -- else print factorial2 5 -- why can't pass here 
      -- else show factorial2 5 -- why can't pass here 
      else putStrLn "Wrong" -- this can pass, no problem 

-- Factorial.hs:10:20: 
--  Couldn't match expected type ‘Integer -> IO()’ 
--     with actual type ‘IO()’ 
--  The function ‘print’ is applied to two arguments, 
--  but its type ‘(a0 -> a0) -> IO()’ has only one 
--  In the expression: print factorial2 5 
--  In a stmt of a 'do' block: 
--  if x == factorial2 5 then putStrLn "Right" else print factorial2 5 
-- Failed, modules loaded: none. 

答えて

3

ハスケル関数適用は左結合である。つまり、print factorial2 5に電話するとき、haskellは2つの引数、すなわちfactorial25を渡すと解釈しますが、印刷には1つの引数しかありません。あなたのコードが別の言語だった場合、それはprint(factorial2, 5)と等価です。

理由はshow factorial2 5はdoブロック内のすべてがIO()を返す必要がありますが、show factorial2 5が文字列を返すためです。

単純にprint (factorial2 5)は、factorial2 5の結果をprintに渡すことを知っているので、haskellが機能するように動作します。

+1

ハスケル(関数アプリケーション)は* left * associativeです: 'print factorial2 5'は'(print factorial2)5'と同じです。 –

+0

@DavidYoungありがとうあなたはまったく正しいです、私の左右を笑いあわせました。私の投稿を編集しました。 –

0

の表示のタイプは、a -> Stringです。 これは1つの引数をとり、それを文字列に変換します。

あなたのラインで

else show factorial2 5 -- why can't pass here 

あなたはの引数、つまりfactorial2とを与えます。

else show (factorial2 5) 

は、多くの場合、あなたが$が表示されます。

あなたはそのため、あなたが持っている括弧の中にfactorial2 5を置くために、あなたのケースで、を表示する機能にfactorial2 5の結果を一つの引数を与えなければなりません演算子:

else show $ factorial2 5 

括弧を保存することができます。

関連する問題