如何检查coask(x,y)在Haskell中的板上是否有效

时间:2017-05-28 08:24:06

标签: haskell

我有一个功能

isValid :: CoOrd -> Bool

其中CoOrd是元组对(x,y)

电路板尺寸为['a'..'h'] ['1'..'8'],因此我想检查给定的CoOrds是否适用于此电路板(CoOrds x < ['a'..'h'], CoOrds y ['1'..'8'])

我对这个问题的逻辑很好,它只是语法,因为我是haskell的新手,所以我正在寻找类似的东西

if (CoOrd(x _) == ['a'..'h'])
    if (CoOrd(_ y) == ['1'..'8'])
        return True
else return False

4 个答案:

答案 0 :(得分:3)

基本方法是使用直接比较:

isValid :: CoOrd -> Bool
isValid (x,y) = x >= 'a' && x <= 'h' && y >= '1' && y <= '8'

更高级的替代方法是利用Data.Ix.inRange

import Data.Ix
isValid :: CoOrd -> Bool
isValid = inRange (('a','1'),('h','8'))

您也可以像其他人指出的那样使用elem,但是elem将扫描整个列表并执行逐点比较(8 + 8比较,在最坏的情况下),而上述方法将只进行四次比较。

最后,对原始代码进行一些评论:

  • 除非您正在编写monadic代码,否则不要在Haskell中使用return
  • 不要使用if condition then True else False - 那个噪音,它相当于conditions。请考虑使用布尔运算符,这通常更简单。

答案 1 :(得分:1)

为什么不为X和Y坐标创建一些新类型,以便类型检查器为您提供任何CoOrd值正确的静态保证?

例如,我认为你有type CoOrd = (Char,Int)。而是尝试:

data XCo = A | B | C | D | E | F | G | H deriving (Eq,Ord,Show,Enum)
data YCo = Y1 | Y2 | Y3 | Y4 | Y5 | Y6 | Y7 | Y8 deriving (Eq,Ord,Enum)

instance Show YCo where
    show y = show (fromEnum y + 1)

type CoOrd = (XCo,YCo)

现在,无论您使用'a''b'等字符文字,都可以使用AB等。与数字和Y轴相同 - {{ 1}}变为1等。

答案 2 :(得分:0)

isValid (x,y) = x `elem` ['a'..'h'] && y `elem` ['1'..'8']

答案 3 :(得分:0)

除了使用其他答案而不是使用元组,您可以定义一个新类型,例如ChessBoard

由于您需要检查输入位置的有效性,因此明智地将其设为Maybe ChessBoard类型。

因此,您可能会想出类似

的内容
module ChessBoard (ChessBoard, chessBoard) where

data ChessBoard = CB Char Int deriving (Eq, Ord, Show)

chessBoard :: Char -> Int -> Maybe ChessBoard
chessBoard c n | elem c ['a'..'h'] && elem n [1..8] = Just (CB c n)
               | otherwise                          = Nothing

在这里您可能会注意到我们没有导出数据构造函数CB Char Int所以创建国际象棋棋盘位置数据的唯一方法是通过chessBoard函数,并且没有非法的棋盘位置。< / p>

我的意思是;

*Main> chessBoard 'a' 3
Just (CB 'a' 3)
*Main> chessBoard 'h' 9
Nothing
*Main> let pos = Just (CB 'a' 11) -- trying to assign an illegal position directly

<interactive>:259:17: error:
    Data constructor not in scope: CB :: Char -> Integer -> a