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
。
答案 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)
删除return
和return True
中的return False
。 return
的类型为
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))