Haskell条件错误

时间:2012-04-15 11:13:25

标签: haskell conditional-statements

我遇到Haskell代码问题,我有以下内容:

takeMeHere cs m =
    |(find (==E) cs == Nothing && (checkNextStep pozxCrt+1 pozyCrt m) == True) = (Just E,[(pozxCrt+1,pozyCrt)] ++ m)
    |(find (==S) cs == Nothing && (checkNextStep pozxCrt pozyCrt-1 m) == True) = (Just S,[(pozxCrt,pozyCrt-1)] ++ m)
    |(find (==W) cs == Nothing && (checkNextStep pozxCrt-1 pozyCrt m) == True) = (Just W,[(pozxCrt-1,pozyCrt)] ++ m)
    |(find (==N) cs == Nothing && (checkNextStep pozxCrt pozyCrt+1 m) == True) = (Just N,[(pozxCrt,pozyCrt+1)] ++ m)
    |otherwise = (Nothing,m)
where
    pozxCrt=fst(head m)
    pozyCrt=snd(head m)

checkNextStep x y m = if(find (== (x,y)) m == Nothing) then True
   else False

我得到parse error on input "|"。如果我用类似if if else的方式编写代码,那么......它的工作原理。但是我想用|为了更紧凑的编码。这里似乎有什么问题?

2 个答案:

答案 0 :(得分:7)

要修复解析错误,请从第一行中删除=。 =符号放在警卫之后。

接下来,你应该缩进"其中"

takeMeHere cs m
    |(find (==E) cs == Nothing && (checkNextStep pozxCrt+1 pozyCrt m) == True) = (Just E,[(pozxCrt+1,pozyCrt)] ++ m)
    |(find (==S) cs == Nothing && (checkNextStep pozxCrt pozyCrt-1 m) == True) = (Just S,[(pozxCrt,pozyCrt-1)] ++ m)
    |(find (==W) cs == Nothing && (checkNextStep pozxCrt-1 pozyCrt m) == True) = (Just W,[(pozxCrt-1,pozyCrt)] ++ m)
    |(find (==N) cs == Nothing && (checkNextStep pozxCrt pozyCrt+1 m) == True) = (Just N,[(pozxCrt,pozyCrt+1)] ++ m)
    |otherwise = (Nothing,m)
  where
    pozxCrt=fst(head m)
    pozyCrt=snd(head m)

这至少会解析,但它不会编译。 (checkNextStep pozxCrt pozyCrt+1 m)应为(checkNextStep pozxCrt (pozyCrt+1) m)

让我补充一点,您可以修复许多冗长的代码:

  • find (==E) cs == Nothing可以更改为E `notElem` x
  • 您无需与True进行比较:将x == True更改为x
  • if x then True else False可以更改为x
  • [x]++y可以更改为x:y
  • 您可以使用这样的模式匹配:(pozxCrt, pozyCrt) = head m(pozxCrt, pozyCrt):_ = m

结果是:

takeMeHere cs m                                                                 
    | E `notElem` cs && checkNextStep (pozxCrt+1) pozyCrt m = (Just E,(pozxCrt+1,pozyCrt):m)
    | S `notElem` cs && checkNextStep pozxCrt (pozyCrt-1) m = (Just S,(pozxCrt,pozyCrt-1):m)
    | W `notElem` cs && checkNextStep (pozxCrt-1) pozyCrt m = (Just W,(pozxCrt-1,pozyCrt):m)
    | N `notElem` cs && checkNextStep pozxCrt (pozyCrt+1) m = (Just N,(pozxCrt,pozyCrt+1):m)
    | otherwise = (Nothing,m)                                                   
  where                                                                         
    (pozxCrt, pozyCrt) = head m                                                 

checkNextStep x y m = (x,y) `notElem` m

你在守卫中有很多重复。很多重复是创造新功能的标志。

move E (x, y) = (x+1, y) 
move S (x, y) = (x, y-1)
move N (x, y) = (x, y+1)
move W (x, y) = (x-1, y)

takeMeHere cs m
    | canGo E = go E
    | canGo S = go S
    | canGo W = go W
    | canGo N = go N
    | otherwise = (Nothing,m)
  where
    pos = head m
    canGo dir = dir `notElem` cs && checkNextStep (move dir pos) m
    go dir = (Just dir, move dir pos:m)

checkNextStep (x, y) m = (x,y) `notElem` m

下一步:使用find canGo [E,S,W,N]摆脱守卫:

 takeMeHere cs m =                                                               
    case find canGo [E,S,W,N] of                                                
      Just dir -> (Just dir, move dir pos:m)                                    
      Nothing -> (Nothing, m) 
    where ...

答案 1 :(得分:3)

我的代码中至少可以看到三个错误。

  • 必须删除第一行的=。在每个=的保护之后,语法需要|。基本上,错误是告诉您第一个管道符号|=之后是意外的,因为后者在该位置使用时没有警卫。
  • 当你给函数输入时,你应该在数学表达式周围加上括号,因为像+这样的中缀运算符在函数应用方面的优先级较低。 checkNextStep pozxCrt+1 pozyCrt m被评估为(checkNextStep pozxCrt) + (1 pozyCrt m)(这显然是一个错误),而不是checkNextStep (pozxCrt+1) pozyCrt m
  • where应相对于第一行缩进。

除非您在省略的代码中有其他错误,否则它应该有效:

takeMeHere cs m    -- no more "=" here
    |(find (==E) cs == Nothing && (checkNextStep (pozxCrt+1) pozyCrt m) == True) = (Just E,[(pozxCrt+1,pozyCrt)] ++ m)
    |(find (==S) cs == Nothing && (checkNextStep pozxCrt (pozyCrt-1) m) == True) = (Just S,[(pozxCrt,pozyCrt-1)] ++ m)
    |(find (==W) cs == Nothing && (checkNextStep (pozxCrt-1) pozyCrt m) == True) = (Just W,[(pozxCrt-1,pozyCrt)] ++ m)
    |(find (==N) cs == Nothing && (checkNextStep pozxCrt (pozyCrt+1) m) == True) = (Just N,[(pozxCrt,pozyCrt+1)] ++ m)
    |otherwise = (Nothing,m)
  where -- indentation
    pozxCrt=fst(head m)
    pozyCrt=snd(head m)

顺便说一句,你的代码是多余的,你应该对所有与True的比较做些什么(参见@ dbaupp对你的问题的评论)。 我建议你再研究一下Haskell的运算符优先级和语法,它将帮助你更好地阅读代码:)