守卫在“do”街区内- haskell

uyto3xhc  于 2022-11-14  发布在  其他
关注(0)|答案(4)|浏览(150)

我想写一个简单的游戏“猜数字”-与n尝试。我想添加一些条件和命中。是否可以使用 guardsdo块?
下面是我的代码:

game = return()
game n = do putStrLn "guess number: 0-99"
            number<-getLine
            let y = read number
            let x =20
            | y>x = putStrLn "your number is greater than x"
            | y<x = putStrLn "your number is less than x"
            | y==x  putStrLn "U win!!"
            | otherwise = game (n-1)

已得到错误

error: parse error on input ‘|’

它是可以用一些 * 白色 * 来修复的,还是不可能做到的?

hec6srdp

hec6srdp1#

一个do表达式[Haskell-report]只包含exppat <- explet …语句,编译器会对这些语句进行反糖处理。因此,如果没有一些语言扩展,您不能在do块中写入保护。此外,无论如何启用它可能不是一个好主意。例如,如果您想使用两个“保护块”,该怎么办紧挨着对方?那么这两个将“合并”,因此第一个街区的警卫将已经消除(几乎)所有的情况。
您可以在此处使用另一个let子句:

game :: IO ()
game 0 = return ()
game n = do
    putStrLn "guess number: 0-99"
    number <- getLine
    let y = read number
    let x = 20
    let action | y > x = putStrLn "your number is greater than x" >> game (n-1)
               | y < x = putStrLn "your number is less than x" >> game (n-1)
               | otherwise = putStrLn "U win!!"
    action

请注意,原始问题中的otherwise永远不会被触发,因为一个值小于、大于或等于另一个值。

mrfwxfqh

mrfwxfqh2#

那里有很多问题
首先,你不能说game =game n =,所以删除game = return ()行(你可能一直在尝试写一个类型签名,但这不是一个)。
第二,你不能在任意的地方使用保护语法,最接近你所写的内容的是多路if表达式,它可以让你写:

{-# LANGUAGE MultiWayIf #-}
game n = do putStrLn "guess number: 0-99"
            number<-getLine
            let y = read number
            let x =20
            if
              | y>x -> putStrLn "your number is greater than x"
              | y<x -> putStrLn "your number is less than x"
              | y==x-> putStrLn "U win!!"
              | otherwise -> game (n-1)

第三,Ord类型类应该用于具有全序的类型,所以除非你使用了像NaN这样的非法对象,否则你总是会有y>xy<xy==x中的一个,所以永远不会输入otherwise
第四,与<==>进行比较既不符合语法又很慢,因为它必须不断地重复比较。与其这样做,不如这样做:

case y `compare` x of
  GT -> _
  LT -> _
  EQ -> _
b4qexyjb

b4qexyjb3#

您也可以只使用caseLambdaCase

{-# LANGUAGE LambdaCase #-}

game  :: Int -> IO ()
game n = case n of
  0 -> putStrLn "used all attempts"
  n -> 
    putStrLn "guess a number: 0 - 99" >>
    (`compare` 20) . read <$> getLine >>= 
      \case 
        EQ -> putStrLn "U win"
        GT -> putStrLn "your number is greater than x" >> 
              game (n - 1)
        LT -> putStrLn "your number is less than x" >> 
              game (n - 1)
fnx2tebb

fnx2tebb4#

其他的答案信息量很大。阅读这些让我看到你也可以调用一个函数来解决这个问题,eidogg。

game = do putStrLn "guess number: 0-99"
          number <- getLine
          let y = read number
          let x = 20
          action y x
       where
           action y x 
            | y>x = putStrLn "your number is greater than x" >> game
            | y<x = putStrLn "your number is less than x" >> game
            | otherwise = putStrLn "U win!!"

相关问题