[英]Converting quarters, dimes, and pennies to dollars and cents in Haskell
我正在嘗試將 25 美分、10 美分和便士轉換為美元和美分,但我似乎無法運行代碼。
我試過這段代碼:
-- Declaration
toCents :: Int -> Int -> Int -> Int
toDollar :: Int -> Int -> Int -> Int
-- Definition
toCents quarter dime penny = quarter*25 + dime*10 + penny
toDollar quarter dime penny = (toCents quarter dime penny) / 100) - ((toCents quarter dime penny mod 100) / 100)
main :: IO()
main = do
let quarter = 12
let dime = 67
let penny = 43
let sumDollar = toDollar quarter dime penny
let sumCents = toCents quarter dime penny - (toDollar quarter dime penny) * 100
print ("Conversion of " ++ show quarter ++ " quarters, " ++ show dime ++ " dimes, and " ++ show penny ++ " pennies to dollars and cents:")
print(sumDollar ++ " dollars and " ++ sumCents ++ " cents.")
它導致了這個錯誤:
[1 of 1] Compiling Main ( main.hs, main.o )
main.hs:7:68: error:
• Couldn't match expected type ‘(Integer -> Integer -> Integer)
-> Integer -> Int’
with actual type ‘Int’
• The function ‘toCents’ is applied to five arguments,
but its type ‘Int -> Int -> Int -> Int’ has only three
In the first argument of ‘(/)’, namely
‘(toCents quarter dime penny mod 100)’
In the second argument of ‘(-)’, namely
‘((toCents quarter dime penny mod 100) / 100)’
|
7 | toDollar quarter dime penny = (toCents quarter dime penny / 100) - ((toCents quarter dime penny mod 100) / 100)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
main.hs:17:8: error:
• Couldn't match expected type ‘[Char]’ with actual type ‘Int’
• In the first argument of ‘(++)’, namely ‘sumDollar’
In the first argument of ‘print’, namely
‘(sumDollar ++ " dollars and " ++ sumCents ++ " cents.")’
In a stmt of a 'do' block:
print (sumDollar ++ " dollars and " ++ sumCents ++ " cents.")
|
17 | print(sumDollar ++ " dollars and " ++ sumCents ++ " cents.")
| ^^^^^^^^^
main.hs:17:40: error:
• Couldn't match expected type ‘[Char]’ with actual type ‘Int’
• In the first argument of ‘(++)’, namely ‘sumCents’
In the second argument of ‘(++)’, namely ‘sumCents ++ " cents."’
In the second argument of ‘(++)’, namely
‘" dollars and " ++ sumCents ++ " cents."’
|
17 | print(sumDollar ++ " dollars and " ++ sumCents ++ " cents.")
|
表達式toCents quarter dime penny mod 100
被解析為
((((toCents quarter) dime) penny) mod) 100
或者
( ( ( (toCents quarter
) dime
) penny
) mod
) 100
這看起來很奇怪,但如果你記住柯里化是如何工作的,它並沒有那么奇怪:它對應於,在一種非柯里化語言中,
toCents(quarter, dime, penny, mod, 100)
這當然仍然是無稽之談:您將mod
作為參數提供給 function toCents
,而不是將其用作運算符。 帶有字母名稱的中綴運算符必須寫在反引號中才能應用它們,例如37`mod`4
,與mod 37 4
相同。 中綴運算符總是綁定弱於前綴 function 應用程序,所以如果你寫了
toCents quarter dime penny `mod` 100
那么這將被解析為
mod (toCents quarter dime penny) 100
這可能是你想要的。 然而,這並不意味着它適合這項任務。 你在做什么
foo/100 - (foo`mod`100)/100
是實現簡單舍入到負數 integer 除法的非常迂回的嘗試。
它在 Python 中有點工作,但即使在那里它也沒有真正做它應該做的事情:Python 自動將整數foo
和100
轉換為浮點數以執行除法,然后相互減去浮點數,結果仍然是浮點數它恰好有零小數部分。
Haskell 甚至不允許這種混亂發生:它會抱怨/
運算符在整數上不可用。 你真的想要那個,你必須明確地轉換為浮點數。
但是您不希望這樣:您應該簡單地使用內置的 integer 除法運算符
toDollar quarter dime penny = toCents quarter dime penny `div` 100
...假設它真的應該有舍入到消極的行為。
更好的方法是正確構建代碼和數據,這將避免冗余計算和神秘的Int -> Int ->...
簽名:
data DollarValue = DollarValue {
dollarPartVal, centPartVal :: Int
}
data DollarCoins = DollarCoins {
quarterCoinCount, dimeCoinCount, pennyCoinCount :: Int
}
coinsValue :: DollarCoins -> DollarValue
coinsValue (DollarCoins q d p) = DollarValue dollars cents
where (dollars, cents) = (25*q + 10*d + p)`divMod`100
import Text.Printf
main = do
let quarter = 12
dime = 67
penny = 43
let DollarValue sumDollars sumCents
= coinsValue $ DollarCoins quarter dime penny
printf
"Conversion of %i quarters, %i dimes, and %i pennies: %i dollars and %i cents.\n"
quarter dime penny sumDollars sumCents
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.