我有一个功能
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
答案 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比较,在最坏的情况下),而上述方法将只进行四次比较。
最后,对原始代码进行一些评论:
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'
等字符文字,都可以使用A
,B
等。与数字和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