2012-09-15 33 views
0

我有一點點曖昧類型變量的問題。我喜歡haskell,但這實際上我仍然無法處理。 這個問題很簡單,涉及到Text.Printf的printf。由於這個問題是很一般我就但在一些示例代碼:用printf和曖昧類型變量的問題

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

addd x y = return (x+y) 

中printf的是進口的。然後編譯器給我一個Num和PrintfArg之間明顯的模糊的類型變量錯誤。我只是不知道在哪裏適合正確的類型簽名。

回答

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) 

然後類型推斷將推斷出4d都是Integer秒。

最後,你可以給d一個類型。無論是當你使用它(如果你使用d多次,你只需要一個註解),像這樣:

printf "%d" (d :: Integer) 

或者當你把它(需要GHC擴展ScopedTypeVariables):

{-# LANGUAGE ScopedTypeVariables #-} 

[...] 
add = do 
    (d :: Integer) <- addd 4 8 
+0

非常感謝您的幫助!但我不得不承認這看起來非常難看。它周圍沒有更漂亮的方法嗎?還有另一個理解問題: 爲什麼只有Num類型的addd返回值是不夠的?爲什麼我必須告訴haskell關於整數? –

+2

啊我看到這是由於要求d是整數類型的合成%d。 –

1

我會盡量解釋什麼是錯的程序。

  • 嘗試給出明確的類型簽名,它有助於編譯器推斷類型,並且更好地理解你的程序。
  • addd是一個純函數,所以不要使用return。
  • 不是你期望來自必要的背景。
  • 爲什麼你需要printf畢竟,使用printputStrLn如果要輸出到控制檯。如果要將類型(其定義的show實例)轉換爲字符串,請使用show

這是你的糾正程序反正

import Text.Printf 

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

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

你可以只使用print作爲

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

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

寫嘗試閱讀一些介紹性的材料上Haskell

+0

背景是在屏幕上使用printf作爲漂亮的表格格式化輸出。我知道基本的印刷說明,但它缺少一些格式化。 –