Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 将函数应用于自定义数据结构的列表_List_Haskell - Fatal编程技术网

List 将函数应用于自定义数据结构的列表

List 将函数应用于自定义数据结构的列表,list,haskell,List,Haskell,根据我先前的问题: 我不想将函数应用于自定义数据结构项的列表。问题是我仍然不知道如何正确处理IO,因此下面是我的代码: data Item = Item { name :: String , expire :: Day , stock :: Integer , price :: Float } deriving (Show) totalLoss :: IO [Item] -> Float totalLoss items = sum $ map lo

根据我先前的问题: 我不想将函数应用于自定义数据结构
项的列表
。问题是我仍然不知道如何正确处理
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)
比如说,我不能只获取
[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
   |                                  ^^^^^
对于
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
   |                                  ^^^^^

我到底该如何解决这个问题呢?

totaloss
是一个纯函数,因此相应地更改其类型:

totalLoss :: [Item] -> Float
totalLoss items = sum $ map loss items
这个问题的根本问题似乎是,物品清单源自不纯净的来源(这是一件完全自然的事情)

编写尽可能多的纯函数代码,然后在
main
函数中(或尽可能接近)使用不纯输入编写这些纯函数:

main :: IO ()
main = do
  items <- ioItems -- :: IO [Item]
  print $ totalLoss items

main
的这两种变体是等效的。

totaloss
的类型更改为
[Item]->Float
,然后使用
fmap
将函数应用于
IO[Item]
类型的值:

totalLoss :: [Item] -> Float
totalLoss items = sum $ map loss items

loss :: Item -> Float
loss x = (price x) * fromIntegral (stock x)

-- fmap totalLoss :: Functor f => f [Item] -> f Float
-- so if you have a value of v :: IO [Item], then
-- fmap totalLoss v :: IO Float

没有(合理的)方法将类型
IO a
作为输入并输出非
IO
类型。您的
totaloss
不涉及
IO
但是-它只需要一个
项的列表
s并输出一个
Float
,因此给它一个适当的类型签名,它应该可以正常工作。(作为一般规则,你永远不应该使用
IO
,除非你必须这样做——也就是说,当你必须与程序之外的世界进行交互时。)嗯,我必须使用IO,因为时间计算和加载CSV。我得到的
Item
s列表是IO[Item],因此没有办法绕过它……我想你误解了。作为一个整体,您的程序可能需要使用IO来获取应用此函数的数据。但函数本身应该尽可能保持“纯”(即不涉及IO)。正如我所说,您已经在
totaloss
中编写了一个类型为
[Item]->Float
的非常好的“pure”函数,编译器不喜欢它的唯一原因是因为您给了它错误的类型签名。在代码的另一部分中,您可以使用
>=
运算符或
do
块从IO操作获取
项的列表,并将其提供给此函数。
totalLoss :: [Item] -> Float
totalLoss items = sum $ map loss items

loss :: Item -> Float
loss x = (price x) * fromIntegral (stock x)

-- fmap totalLoss :: Functor f => f [Item] -> f Float
-- so if you have a value of v :: IO [Item], then
-- fmap totalLoss v :: IO Float