【问题标题】:Can I use guards within guards in Haskell我可以在 Haskell 的守卫中使用守卫吗
【发布时间】:2023-09-13 12:22:01
【问题描述】:

我在 Haskell 的守卫中尝试使用守卫时遇到了一个问题,我试图找出是否(不可能)这样做,但我在互联网上找不到任何答案,我希望你小伙伴们可能知道答案了。这是我在尝试编译代码时遇到的错误: Assignment2.hs:134:75: parse error on input '|'

我的代码:

    verticals :: Board -> (Row, Row, Row)   
    verticals ((a,b,c),(d,e,f),(g,h,i)) = ((a,d,g),(b,e,h),(c,f,i))

    symbolToPlayer :: Field -> Player   
    symbolToPlayer X = P1  
    symbolToPlayer O = P2

    showTime :: Board -> Maybe Player  
    showTime ((a,b,c),(d,e,f),(g,h,i))
                        | a==b && a==c = Just (symbolToPlayer a)          
                        | d==e && d==f = Just (symbolToPlayer d)  
                        | g==h && g==i = Just (symbolToPlayer i)
                        | otherwise = False

    hasWinner :: Board -> Maybe Player  
    hasWinner b@((a,b,c),(d,e,f),(g,h,i))       
                                   | showTime b        -> spot of error
                                   | showTime (verticals b)
                                   | a==e && a==i = Just (symbolToPlayer a)
                                   | c==e && c==g = Just (symbolToPlayer c)
                                   | otherwise = Nothing

代码是一个井字游戏的代码,这部分代码应该找出哪个玩家赢了;类型Board自定义,输入示例:hasWinner((X,O,X),(X,O,O),(X,X,O))(​​输出应为:Just P1)。

感谢您的帮助!

【问题讨论】:

  • 您是否检查过所有的空格都是空格而不是制表符?该函数的获胜者也是->而不是=
  • 我想知道您为什么希望它编译,以及它应该如何工作。显然你想以某种方式评估showTimeMaybe 结果?

标签: haskell guard


【解决方案1】:

您的程序中至少有 2 个严重的语法错误和一个类型错误。

语法错误:

    | showTime b        -> spot of error
    | showTime (verticals b)

这里缺少右手边。一般形式是

    | guard = expression

没有表情就无法逃脱。编译器等待'=',但找到'|'下一个守卫的,所以它知道自己有问题。

类型错误在这里:

    | g==h && g==i = Just (symbolToPlayer i)
    | otherwise = False

您必须决定函数应该返回Bool 还是Maybe Player

【讨论】:

    【解决方案2】:

    这个怎么样?

    import Control.Monad (msum)
    import Control.Applicative ((<*>), pure)
    
    data Player = P1 | P2 | None deriving (Eq, Show)
    
    data Field = X | O | B deriving (Eq, Show)
    
    type Board = ((Field, Field, Field)
                 ,(Field, Field, Field)
                 ,(Field, Field, Field))
    
    symbolToPlayer :: Field -> Player
    symbolToPlayer X = P1
    symbolToPlayer O = P2
    symbolToPlayer B = None
    
    checkThree :: (Field,Field,Field) -> Maybe Player
    checkThree (a,b,c)
        | a == b && a == c = Just $ symbolToPlayer a
        | otherwise        = Nothing
    
    winHorizontal :: Board -> Maybe Player
    winHorizontal (r1, r2, r3) = msum $ map checkThree [r1, r2, r3]
    
    winVertical :: Board -> Maybe Player
    winVertical ((a,b,c), (d,e,f), (g,h,i)) =
        msum $ map checkThree [(a,d,g), (b,e,h), (c,f,i)]
    
    winDiagonal :: Board -> Maybe Player
    winDiagonal ((a,_,c), (_,e,_), (g,_,i)) =
        msum $ map checkThree [(a,e,i), (c,e,g)]
    
    hasWinner :: Board -> Maybe Player
    hasWinner b = msum $ [winHorizontal, winVertical, winHorizontal] <*> pure b
    

    Monad 和 Applicative 是你的朋友!

    【讨论】:

      最近更新 更多