我试图做一个检查功能,但我收到了错误:
Couldn't match expected type `Char' with actual type `[Char]'
Expected type: [Char]
Actual type: [[Char]]
In the first argument of `isHorizontal', namely `str'
In the expression: isHorizontal str number
这是触发它的功能:
upCheck :: [[Char]] -> Int -> [Int] -> Bool
upCheck tableArr number posArr = do
let arv = findVertIndex (tableArr !! (posArr !! 0)) number
let str = tableArr !! (posArr !! 0)
if ((posArr !! 0) == 1)
then False
else if isHorizontal str number
then False
else if (tableArr !! ((posArr !! 0)-1)) !! arv /= 'x'
then False
else True
其中tableArr
是包含字符串的数组:["2323","3232","3231","3232"]
和posArr
是包含正确位置的数组,例如[1,3]
。 number
是我们要检查的号码,让我们说1
。
现在isHorizontal
函数就是这个,它基本告诉我同一行中是否有两个元素。
isHorizontal :: [Char] -> Int -> Bool
isHorizontal [] _ = False
isHorizontal [x] _ = False
isHorizontal (x:y:xs) number =
if (firstCheck x && firstCheck y)
then (if digitToInt(x) == number && digitToInt(y) == number then True else isHorizontal xs number)else isHorizontal (y:xs) number
但是函数isHorizontal适用于输入" 55x32"例如5,所以问题出在我的upCheck功能中。从它的外观来看,代码:tableArr !! (posArr !! 0)
也应该给一个字符串,所以这应该适合isHorizontal函数,但它不会...
我错过了什么?
编辑:
将类型添加到函数后,错误更改为:
Couldn't match expected type `[Char]' with actual type `Char'
Expected type: [[[Char]]]
Actual type: [[Char]]
In the first argument of `(!!)', namely `tableArr'
In the first argument of `findVertIndex', namely
`(tableArr !! (posArr !! 0))'
答案 0 :(得分:4)
您正在尝试在此处定义纯函数。 (那个伟大的,纯粹的功能给你referential transparency:非常好的推理你的程序将如何表现!)
但是,do
符号是程序性的。当你正在做 impure 的东西†时(例如,如果你有签名[[Char]] -> Int -> [Int] -> IO Bool
,你需要那个,这意味着你的“功能”是也允许做不纯的顺序IO操作)。但是在编写简单的纯函数时,你并不需要这样做。
所以而不是
upCheck tableArr number posArr = do
let arv = findVertIndex (tableArr !! (posArr !! 0)) number
let str = tableArr !! (posArr !! 0)
if ((posArr !! 0) == 1)
then False
else if isHorizontal str number
then False
else if (tableArr !! ((posArr !! 0)-1)) !! arv /= 'x'
then False
else True
你可能想要
upCheck tableArr number posArr
= let arv = findVertIndex (tableArr !! (posArr !! 0)) number
str = tableArr !! (posArr !! 0)
in if ((posArr !! 0) == 1)
then False
else if isHorizontal str number
then False
else if (tableArr !! ((posArr !! 0)-1)) !! arv /= 'x'
then False
else True
这看起来很相似,但实际上做了一些完全不同的事情:而不是用do
(仅适用于像IO
这样的monad中的一系列步骤进行硬烘焙),你只需告诉它编译器的一些定义,但可以自由地找出评估这些定义的最佳顺序。
实际上,按照
这样的方式更多地写出定义是习惯做法upCheck tableArr number posArr
= if ((posArr !! 0) == 1)
then False
else if isHorizontal str number
then False
else if (tableArr !! ((posArr !! 0)-1)) !! arv /= 'x'
then False
else True
where arv = findVertIndex (tableArr !! (posArr !! 0)) number
str = tableArr !! (posArr !! 0)
实际上与let...in
的代码完全相同。
请注意if
staments链可以更好地编写为 guards :
upCheck tableArr number posArr
| posArr!!0 == 1 = False
| isHorizontal str number = False
| tableArr !! ((posArr !! 0)-1)) !! arv /= 'x' = False
| otherwise = True
where arv = findVertIndex (tableArr !! (posArr !! 0)) number
str = tableArr !! (posArr !! 0)
......但实际上,在编写 boolean 函数时,您根本不需要条件。整个野兽等同于简单
upCheck tableArr number posArr
= not ( posArr!!0 == 1
|| isHorizontal str number
|| tableArr !! ((posArr !! 0)-1)) !! arv /= 'x'
)
where arv = findVertIndex (tableArr !! (posArr !! 0)) number
str = tableArr !! (posArr !! 0)
这在大多数编程语言中都是可行的,而不仅仅是在Haskell中。
† 实际上,do
本身并不纯洁。它使用 monads ,恰好允许(除此之外)将不纯的代码嵌入到纯Haskell中(以一种非常安全的方式)。但是你可能想稍后了解它。