Guard在'do'块内-haskell

问题描述 投票:3回答:3

我想编写一个简单的游戏“猜号码”-尝试n。我想添加一些条件和点击。是否可以在do块内使用guards

这是我的代码:

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 ‘|’

它是否可以用某些空格固定,或者根本无法做到?

haskell syntax do-notation guard-clause
3个回答
5
投票

do expression [Haskell-report]仅由doexppat < exp语句组成,并且编译器将对它们进行解糖。因此,如果没有某些语言扩展,则无法在let …块中编写防护。此外,启用该功能可能不是一个好主意。例如,如果您想彼此相邻使用两个“防护块”怎么办?然后这两个将“合并”,因此第一个块的警卫将已经(几乎)清除所有情况。

您可以在此处使用另一个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永远不会被触发,因为一个值小于,大于或等于另一个值。


6
投票

那里有很多问题。

首先,您不能说otherwisegame =,因此请删除game n =行。 (您可能一直在尝试编写类型签名,但这不是一个。)

第二,您不能在任意地方使用警卫语法。与您写的内容最接近的有效内容是game = return (),可以让您编写以下内容:

multi-way if-expressions

第三,{-# 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) 类型类应该用于具有总顺序的类型,因此,除非您使用的是诸如NaN之类的非法内容,否则您将始终拥有Ordy>xy<x中的一种,因此将永远不会输入y==x

第四,与otherwise<==进行比较是单项且缓慢的,因为它必须不断重复比较。不要这样做,而是执行以下操作:

>

3
投票

您也可以只使用case y `compare` x of GT -> _ LT -> _ EQ -> _ case

LambdaCase
© www.soinside.com 2019 - 2024. All rights reserved.