String 将字符串解析为二进制元组列表
我正在尝试将Haskell中的字符串String 将字符串解析为二进制元组列表,string,parsing,haskell,tuples,lambda-calculus,String,Parsing,Haskell,Tuples,Lambda Calculus,我正在尝试将Haskell中的字符串“A1B2C3D4”解析为[('a',1),('B',2),('C',3)] 我试图使用一个map像这样的map(\[a,b]->(a::Char,b::Int))x,其中x是字符串 这是我需要遵循的函数签名::String->[(Char,Int)] 不幸的是,我得到了类型不匹配,有人能给出任何提示如何解决这个问题吗 我的方向正确吗?有几个问题 map(\[a,b]>…)x中的模式[a,b]仅匹配两个元素的列表,因此编译器推断函数\[a,b]>…对于某些r和
“A1B2C3D4”
解析为[('a',1),('B',2),('C',3)]
我试图使用一个map
像这样的map(\[a,b]->(a::Char,b::Int))x
,其中x
是字符串
这是我需要遵循的函数签名::String->[(Char,Int)]
不幸的是,我得到了类型不匹配,有人能给出任何提示如何解决这个问题吗
我的方向正确吗?有几个问题
map(\[a,b]>…)x中的模式[a,b]
仅匹配两个元素的列表,因此编译器推断函数\[a,b]>…
对于某些r
和s
具有类型[r]>s
编译器知道map
具有类型(u->v)->[u]->[v]
,因此它将u
与[r]
和v
与s
相结合,以推断map(\[a,b]->)的类型[[r]]->[s]
这意味着x
必须具有类型[[r]]
,也就是说,它必须是列表列表。但是您希望x
成为字符串,它是[Char]
的同义词。编译器无法统一[[r]]
和[Char]
,因此它会创建对象
a
转换为Char
并将b
转换为Int
,就像在C中一样,但在Haskell中不能这样做。如果要将字符
如'1'
转换为Int
1
,则需要另一种方法,如读取
,可以使用该方法将字符串
转换为Int
map
。尝试编写一个递归解决方案
首先考虑几个案例:
返回什么myParser”“
返回什么myParser“a1”
返回什么myParser[a,b]
返回什么myParser(a:b:cs)
map(\[a,b]>…)x中的模式
仅匹配两个元素的列表,因此编译器推断函数[a,b]
对于某些\[a,b]>…
和r
具有类型s
编译器知道[r]>s
具有类型map
,因此它将(u->v)->[u]->[v]
与u
和[r]
与v
相结合,以推断s
map(\[a,b]->)的类型
这意味着[[r]]->[s]
必须具有类型x
,也就是说,它必须是列表列表。但是您希望[[r]]
成为x
字符串,它是
的同义词。编译器无法统一[Char]
和[[r]]
,因此它会创建对象[Char]
- 您正试图将
转换为a
并将Char
转换为b
,就像在C中一样,但在Haskell中不能这样做。如果要将Int
如字符
转换为'1'
Int
,则需要另一种方法,如1
,可以使用该方法将读取
转换为字符串
Int
这里有一些建议。不要使用
- 有几个问题
map
。尝试编写一个递归解决方案
首先考虑几个案例:
返回什么myParser”“
返回什么myParser“a1”
返回什么myParser[a,b]
返回什么myParser(a:b:cs)
“AA11B2C3”
应该真正检查
(a:b:rest)
中的a
和b
是否确实是Char
和Int
。此外,它使用递归,您提到使用map
可能还不够,而且它的类型非常多态。我提出了这个方法,但它确实不安全,因为它不会处理不正确的字符串,如“AA11B2C3”
应该真正检查
(a:b:rest)
中的a
和b
是否确实是Char
和Int
。此外,它还使用递归,您提到使用map
可能不够,而且它的类型非常多态。好吧,map
实际上是用于将单个函数逐个应用于某个元素。如何拆分字符串需要上下文(知道下一个字母),因此map
不是最佳选择
但是,您说过您的解决方案必须符合map
。这是可以做到的,但有点迂回。我想不出任何方法使map
拆分实际字符串,但它肯定可以用于将其转换为正确的类型:
isDigit :: Char -> Bool
isDigit c = elem c ['0'..'9']
split :: String -> [(Char, Int)]
split str = let chars = filter (not . isDigit) str
nums = filter isDigit str
zipped = zip chars nums in
map (\(a, b) -> (a, read [b])) zipped
嗯,
map
实际上是指将单个函数逐个应用于某个元素。如何拆分字符串需要上下文(知道下一个字母),因此map
不是最佳选择
但是,您说过您的解决方案必须符合map
。这是可以做到的,但有点迂回。我想不出任何方法使map
拆分实际字符串,但它肯定可以用于将其转换为正确的类型:
isDigit :: Char -> Bool
isDigit c = elem c ['0'..'9']
split :: String -> [(Char, Int)]
split str = let chars = filter (not . isDigit) str
nums = filter isDigit str
zipped = zip chars nums in
map (\(a, b) -> (a, read [b])) zipped
正如其他人指出的,您需要了解
map
将给定函数应用于列表中的每个成员。一旦理解了这一点,您就会意识到,通过在现有列表上应用函数,无法获得所需的转换
这使我们认识到,一旦你有了“A1”、“B2”的列表,。。。这个
isDigit :: Char -> Bool
isDigit c = elem c ['0'..'9']
split :: String -> [(Char, Int)]
split str = let chars = filter (not . isDigit) str
nums = filter isDigit str
zipped = zip chars nums in
map (\(a, b) -> (a, read [b])) zipped
import Data.Char
split' :: String -> [String]
split' [] = []
split' (x:y:xs) = (x:[y]) : split' xs
convert :: String -> [(Char, Int)]
convert input = map (\s -> (s!!0 , digitToInt(s!!1) )) $ split' input