1

少しあいまいな型変数の問題があります。私はhaskellが大好きですが、これは本当に私がまだ処理できないものです。問題は非常に簡単で、Text.Printfのprintfが関係しています。問題は非常に一般的であるため、いくつかのサンプルコードで説明します。

program = do
    d <- addd 4 8
    printf "%d" d

addd x y = return (x+y)

もちろん、printfはインポートされます。次に、コンパイラーは、NumとPrintfArgの間の明白で曖昧な型変数エラーを私に与えます。適切な型署名のどこに収まるかわかりません。

4

2 に答える 2

2

型シグネチャを配置できる場所がいくつかあります。まず、addd には最も一般的な型があります (そして、最も一般的な型は (ほぼ常に) 署名を省略したときに GHC が推測するものです):

addd :: (Monad m, Num a) => a -> a -> m a

明示的な型シグネチャを指定することで、これを特定の型でのみ機能するように制限できます。これによりaddd、引数がまったくポリモーフィックにならなくなります。たとえば、次のようになります。

addd :: Monad m => Int -> Int -> m Int
-- or,
addd :: Monad m => Integer -> Integer -> m Integer

または、 を呼び出すときに GHC に入力タイプを通知することもできますaddd。たとえば、次のようになります。

d <- addd 4 (8 :: Integer)

型推論は、4anddが両方ともIntegers であることを推論します。

最後に、タイプを指定できますd。それを使用するとき (d複数回使用する場合、必要な注釈は 1 つだけです)、次のようになります。

printf "%d" (d :: Integer)

または、それを設定するとき (GHC 拡張機能が必要ですScopedTypeVariables):

{-# LANGUAGE ScopedTypeVariables #-}

[...]
add = do
    (d :: Integer) <- addd 4 8
于 2012-09-15T10:13:13.540 に答える
1

あなたのプログラムの何が問題なのかを説明しようと思います。

  • 明示的な型シグネチャを与えてみてください。コンパイラが型を推測し、プログラムをよりよく理解するのに役立ちます。
  • addd は純粋な関数なので、return は使用しないでください。
  • 不可欠な背景から来ると期待するものではありません。
  • 結局なぜ必要なのか、コンソールに出力したい場合はorprintfを使います。タイプ (インスタンスが定義されている) を文字列に変換する場合に使用します。printputStrLnshowshow

とにかく、ここにあなたの修正されたプログラムがあります

import Text.Printf

program :: String
program = do
    let d = addd 4 8
    printf "%d" d

addd :: Int -> Int -> Int
addd x y = x+y

printasだけで書けます。

program :: IO ()
program = do
    print $ addd 4 8

addd :: Int -> Int -> Int
addd x y = x+y

Haskellの入門資料を読んでみてください

于 2012-09-15T10:12:57.213 に答える