haskell将字符串转换为Int

时间:2019-02-27 18:58:20

标签: haskell

我正在尝试创建一个函数,该函数使用下面定义的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))时,程序将充满错误。我不知道该如何解决:(

3 个答案:

答案 0 :(得分:2)

问题是您将CharString混淆了。

当您将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的同义词。由于类型不匹配,因此无法为findLetterwhere 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必须是字符串列表。 如果改写accoListfindLetter以接受Chars,ghci会推断s是一个Chars List,它是一个字符串。这样您的原始签名就可以了。

假设这是用于国际象棋游戏,那么使用Chars而不是Strings还是比较可取的,因为位置只能是单个字母。