从Haskell中的列表列表中过滤

时间:2011-11-20 16:38:15

标签: haskell

findit::[Productdb]->Bool
findit para = do
          let para1 = head para
          let para2 = head [b|(a,b,c,d)<-para1]
          if(para2=="him") then return False
          else return True
test = do 
    u <- readFile "cart1.txt"
    let v = read u ::[[Productdb]]
    let putit=filter findit v
    putStrLn(show(putit)

执行时,我收到findit返回IO Bool而不是Bool的错误,filter语句出现错误,它只接受返回的函数Bool

3 个答案:

答案 0 :(得分:6)

Do-notation仅适用于IO等monad。 findit返回普通Bool,因此您不应使用do-notation来定义它。你可以这样写:

findit para = let para1 = head para
                  para2 = head [b|(a,b,c,d)<-para1]
              in  if (para2=="him") then False else True

请注意,他使用的是let ... in ...表达式,而不是逗号表示允许的let形式。

然而,这不是非常惯用的Haskell。 if表达式可以替换为para2 /= "him"head的应用程序和列表推导可以替换为模式匹配:

findit (((_, b, _, _):_):_) = b /= "him"

现在,你的函数 total 也很容易,所以它也是通过在它下面添加一个包含所有案例的空列表来定义的:

findit _ = -- something that makes sense for your use case

这通常是一个好主意,因为总功能更好用,因为它们不会因意外输入而失败。

最后,我建议为代码中的变量和函数选择更好的名称。看看你的代码,我可以告诉它在“机械”级别上做了什么,但我不知道是什么,或者即使它正在做它应该做的事情。对事物进行命名是帮助将意图传达给其他程序员的重要方法。

答案 1 :(得分:3)

删除returnreturn True中的return Falsereturn的类型为

return :: Monad m => a -> m a

似乎m默认为IO,但无论如何,findit是一个普通函数 - 无需返回。

答案 2 :(得分:1)

我仍然不知道你要做什么,但我会给你一些类似于我想你想要的代码。

type Code=Int
type Name= String
type Price = Int
type Quantity= Int
type Product = (Code, Name, Price, Quantity)

-- test data
product1 = (1, "one", 123, 111)
product2 = (2, "two", 321, 11)
product3 = (3, "three", 44, 1)
product4 = (4, "him", 55, 22)
product_db = [[product1, product2], [product4, product2], [product3]]

-- @Hamanshi: please explain how this could make sense (especially the call to head seems suspicious)
findit :: [Product] -> Bool
findit para = let para2 = head [b | (a,b,c,d) <- para] in para2 /= "him"

test :: IO ()
test = putStrLn $ show $ filter findit product_db

我将Productdb更改为Product因为我认为元组代表单个产品,而不是产品数据库。

此外,您可以使用实际数据类型:data Product = Product { code :: Code, name :: Name, price :: Price, quantity :: Quantity },这将为您提供产品选择器name product1 == "one" 然后你可以用这种方式重写find:findit para = "him" /= (name (head para))