因此,我有以下功能:
chk2 :: [(Integer,Integer)] -> Either [(Integer,Integer)] (Integer,Integer)
chk2 i@((n,_):_)
| chkp (prod $ lgst i)==True = Right $ lgst i
| lgst i==i!!0 = Left $ chk2 $ (4-2,4-2):next i
| otherwise = Left $ chk2 $ next i
where prod (a,b) = a*b
lgst = foldl1 (\(a,b) (c,d) -> if prod (a,b) > prod (c,d) then (a,b) else (c,d))
next t = map (\(a,b) -> if (a,b)==lgst t then (a-1,b+1) else (a,b)) t连同这个错误:
runhugs: Error occurred
ERROR "4/4.hs":14 - Type error in explicitly typed binding
*** Term : chk2
*** Type : [(Integer,Integer)] -> Either (Either [(Integer,Integer (Integer,Integer)) (Integer,Integer)
*** Does not match : [(Integer,Integer)] -> Either [(Integer,Integer)] (Integer,Integer)我试图让这个函数得到一个(a,b),即第一个守卫,或者(a,b),即后两个守卫。最基本的问题是后两名警卫。如果去掉递归,一切都会正常工作,但我不知道如何在返回函数本身时定义类型签名。
发布于 2011-01-23 00:51:45
问题是你怎么恢复。
根据chk2的类型,chk2 $ next i属于Either [(Integer,Integer)] (Integer,Integer)型。Left是b -> Either b a类型,因此对于某些未指定类型的a,Left $ chk2 $ next i是Either (Either [(Integer,Integer)] (Integer,Integer)) a类型。
Left $ chk2 $ (4-2,4-2):next i也有类似的问题。
要修复,您需要决定如何处理递归值。
容易修复:
| lgst i==i!!0 = chk2 $ (4-2,4-2):next i
| otherwise = chk2 $ next i然而,我怀疑这是您想要的,因为这意味着您的所有结果将是Right。我不知道怎么做你想做的,因为我不知道你想要什么。
列表结果意味着什么?无名单的结果意味着什么?
您可能要做的是,模式匹配递归的结果,转换Right pair -> Left [pair],或者将其他一些结果附加到前面。
例如,我将构造一个具有类似类型签名的递归函数。设foo是一个接受整数列表的函数,并且:
为此,请执行以下操作:
foo :: [Integer] -> Either [Integer] Integer
foo [] = Left []
foo (x:xs) = case foo xs of
Left ys -> if all (<=x) ys
then Right x
else let (_,ys') = break (>x) ys in Left (x:ys')
Right y -> if x >= y
then Right x
else Left [x,y]注意如何使用case对foo的递归调用结果进行模式匹配。
发布于 2011-01-24 00:58:24
要解决欧拉#4,你的似乎是一个非常尴尬的风格Haskell。尝试将其他语言的“端口”代码移植到Haskell通常是个坏主意,因为Haskell的范例非常不同。
您将找到一个非常干净、合理的Euler #4解决方案,它使用列表理解在Haskell Wiki。当然不是唯一的解决方案,但它至少与当前代码一样可读性为20倍。无意冒犯。
我(和许多其他Haskeller)强烈推荐给你一个哈斯克尔和真实世界Haskell来学习如何以Haskell的方式处理问题,在我的经验中,通常是创建小型的简单助手方法并将它们组合成一个解决方案。
https://stackoverflow.com/questions/4771584
复制相似问题