源自我之前的问题:天之间的计算差异
我不想将函数应用于自定义数据结构的列表Item。问题是我仍然不知道如何IO正确处理,因此这是我的代码:
data Item = Item
{ name :: String
, expire :: Day
, stock :: Integer
, price :: Float
} deriving (Show)
totalLoss :: IO [Item] -> Float
totalLoss items = sum $ map loss items
loss :: Item -> Float
loss x = (price x) * fromIntegral (stock x)
Run Code Online (Sandbox Code Playgroud)
只是说,我不能得到公正,[Item]所以我必须处理IO适当的事情。但是无论如何我仍然会遇到这些错误:
• Couldn't match expected type ‘[IO Item]’
with actual type ‘IO [Item]’
• In the second argument of ‘map’, namely ‘items’
In the second argument of ‘($)’, namely ‘map loss items’
In the expression: sum $ map loss items
|
48 | totalLoss items = sum $ map loss items
| ^^^^^
Run Code Online (Sandbox Code Playgroud)
同loss :: IO Item -> Float一个错误,loss :: IO [Item] -> Float另一个错误。
• Couldn't match expected type ‘[IO [Item]]’
with actual type ‘IO [Item]’
• In the second argument of ‘map’, namely ‘items’
In the second argument of ‘($)’, namely ‘map loss items’
In the expression: sum $ map loss items
|
48 | totalLoss items = sum $ map loss items
| ^^^^^
Run Code Online (Sandbox Code Playgroud)
我应该如何解决这个问题?
totalLoss 是一个纯函数,因此请相应地更改其类型:
totalLoss :: [Item] -> Float
totalLoss items = sum $ map loss items
Run Code Online (Sandbox Code Playgroud)
这个问题的根本问题似乎是项目清单源自不纯的来源(这是完全自然的事情)。
编写尽可能多的代码作为纯函数,然后使用(或尽可能接近)该main函数的不纯输入来构成这些纯函数:
main :: IO ()
main = do
items <- ioItems -- :: IO [Item]
print $ totalLoss items
Run Code Online (Sandbox Code Playgroud)
作为暗示的评论,ioItems有型IO [Item],但你可以撰写totalLoss与items通过do符号。
如果您不想依靠do符号,也可以在没有语法糖的情况下编写函数:
main :: IO ()
main = fmap totalLoss ioItems >>= print
Run Code Online (Sandbox Code Playgroud)
的这两个变体main是等效的。