我正在尝试创建一个函数,该函数使用下面定义的findLetter函数将字符串B1 C2转换为两个int元组。 B = 2和C =3。这还将反转元组顺序。因此B1 C5 ==((1,2 ,,(5,3))。
accoList = [("A", "1"),("B", "2"),("C", "3"),("D", "4"),("E", "5"),
("F", "6"),("G", "7"),("H", "8")]
findLetter :: String -> String
findLetter c = findLetter' c accoList
where findLetter' c ((x,y):xs) = if x == c then y else findLetter' c xs
findLetter' c [] = undefined
--userToMove1 :: String -> ((Int, Int),(Int, Int))
userToMove1 s = userToMove' $ take 5 s
where userToMove' (a:b:c:d:e:xs) = ((read b , (read (findLetter a))),((read e), (read (findLetter d))))
当我运行这段代码时,会遇到非穷举模式之类的异常,并且当我不注释掉--userToMove1 :: String -> ((Int, Int),(Int, Int))
时,程序将充满错误。我不知道该如何解决:(
答案 0 :(得分:2)
问题是您将Char
与String
混淆了。
当您将String
与(a:b:c:d:e:xs)
进行模式匹配时,除xs
之外的所有元素实际上都是Char
而不是String
-这就是为什么xs
的末尾带有“ s”,请记住字符串是列表。
因此,findLetter应该具有签名findLetter :: Char -> String
,因为它从Char
提取userToMove1
并从accoList
返回一个字符串
对于findLetter返回一个String来说,这实际上没有任何意义,您可以读取findLetter
本身中的字符串,甚至可以在元组中添加一个Int。我就是这样写的:
accoList = [('A', 1),('B', 2),('C', 3),('D', 4),('E', 5),('F', 6),('G', 7),('H', 8)]
findLetter :: Char -> Int
findLetter c = findLetter' c accoList
where findLetter' c ((x,y):xs)
| x == c = y
| otherwise = findLetter' c xs
userToMove1 :: String -> ((Int, Int),(Int, Int))
userToMove1 s = userToMove' $ take 5 s
where userToMove' (a:b:c:d:e:[]) = ((read b , findLetter a),(read e, findLetter d))
最后,我想说的是这段代码看起来很奇怪,并且可能有更好的方法来实现您想要实现的目标
答案 1 :(得分:1)
您的模式匹配(a:b:c:d:e:xs)
采用字符串的前5个字符;每个都是Char
类型,而不是String
类型,[Char]
是read
的同义词。由于类型不匹配,因此无法为findLetter
或where userToMove' (a:b:c:d:e:xs) = ((read [b] , (read (findLetter [a]))),((read [e]), (read (findLetter [d]))))
找到合适的函数。
您可以通过将字符转换回字符串来解决当前的问题,
findLetter
此外,您可以将findLetter c = fromJust $ lookup c accoList
重新定义为:
function doRequest() {
return dispatch => {
makeRequest()
.catch(error => {
if (isUnauthorizedError(error)) {
return refreshToken().then(makeRequest);
}
throw error;
})
.then(
doRequestSuccess,
doRequestFailure
);
}
}
答案 2 :(得分:0)
在ghci中,您可以使用:t userToMove1
来检查函数的推断类型。您的情况返回:
*Main> :t userToMove1
userToMove1
:: (Read t, Read t1, Read t2, Read t3) =>
[String] -> ((t3, t2), (t1, t))
ghci推断您的输入参数是一个字符串列表,而不只是您想要的字符串。
为什么会这样?
在userToMove1
中,对列表进行模式匹配,然后将列表中的元素提供给findLetter
函数。那些期望使用字符串,因此匹配的元素(a,b,c,d,e)必须是字符串,因此s
必须是字符串列表。
如果改写accoList
和findLetter
以接受Chars,ghci会推断s
是一个Chars List,它是一个字符串。这样您的原始签名就可以了。
假设这是用于国际象棋游戏,那么使用Chars而不是Strings还是比较可取的,因为位置只能是单个字母。