Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 从字符串列表中读取数据_Haskell - Fatal编程技术网

Haskell 从字符串列表中读取数据

Haskell 从字符串列表中读取数据,haskell,Haskell,我有一个这样的数据结构 data Something = Something Integer String String 我想改变信仰 ["Something", "3", "text", "42"] 对数据进行修改 现在,我有 altRead :: Read a => [String] -> a altRead = read . unwords . hack where hack = map (\x -> if isNumber x then

我有一个这样的数据结构

data Something = Something Integer String String
我想改变信仰

["Something", "3", "text", "42"] 
对数据进行修改

现在,我有

altRead :: Read a => [String] -> a
altRead = read . unwords . hack
    where 
        hack = map (\x -> if isNumber x then x else "\"" ++ x ++ "\"")
        isNumber = foldl (\b c -> isDigit c && b) True 
但我忘了,有些数字可能是数据结构中的字符串。
是否有一个简单的解决方案,或者我需要编写一个替代的ReadTypeClass

就您所拥有的,您实际上不需要将它变成一个typeclass。您只需执行以下操作:

readSomething :: [String] -> Maybe Something
readSomething [_, n, s1, s2] = Just $ Something (read n) s1 s2
readSomething _              = Nothing
或者,如果要消除第一个单词的歧义:

data Something = Something Integer String String
               | SomethingToo String Integer

readSomething :: [String] -> Maybe Something
readSomething ["Something", n, s1, s2] = Just $ Something (read n) s1 s2
readSomething ["SomethingToo", s, n]   = Just $ SomethingToo s (read n)
readSomething _                        = Nothing
在GHCI中:

data Something = Something Integer String String deriving (Read, Show)

let somethingStrings = ["Something", "3", "text", "42"]

let escapeForSomething [a,b,c,d] = [a, b, "\""++c++"\"", "\""++d++"\""]

let something = read (unwords (escapeForSomething somethingStrings)) :: Something

您正在一些词法复杂的标记上编写一个小型解析器。您不能真正实现
Read
实例,因为
Read::Read a=>String->a
并且您想要为
a==Something
执行
[String]->a
。例如,您可以利用已经存在的
Read
实例来引导解析您的
整数

让我们试试看。我们将从标记列表中解析
某物

import Safe -- gives us readMay :: Read a => String -> Maybe a

parseSomething :: [String] -> Maybe Something
parseSomething ("Something":strInt:stra:strb:_) = 
  do int <- readMay strInt
     return $ Something int stra strb
parseSomething _ = Nothing
实际上,我们可能还应该返回任何未使用的标记,以便继续解析

parseSomething :: [String] -> (Maybe Something, [String])
parseSomething ("Something":strInt:stra:strb:rest) = 
  (Something <$> readMay strInt <*> pure stra <*> pure strb, rest)
parseSomething rest = (Nothing, rest)
parseSomething::[String]->(可能是[String])
解析某物(“某物”:strInt:stra:strb:rest)=
(某物读起来可能是纯stra纯strb,休息)
parseSomething rest=(无,rest)


我将所有这些结构引入到解析中的原因是,它开始朝向解析器组合符的空间,如
Parsec
。每当您需要一个复杂的
读取
时,查看Haskell中的一些非常好的解析库就变得非常有用了。

根据示例中的当前列表,无法绕过
hack
函数,因为并非所有元素都是可读的。您使用列表而不是
“Something 3\”text\“42”
,这有什么原因吗?是的,我从解析器那里得到了这个列表,但解析器不知道类型。但我不会更改数据结构,因为我有很多大的和不同的结构,这将是太多的开销。你真的需要添加
::Integer
读取n
?类型检查器应该能够找到它。实际上,类型注释是不必要的。您确实不应该建议
error
来指示解析失败。。。这就像是因为火警警报响起而炸毁了整个城市。捕获一个
中的失败,可能
/
或者
单子。@tel:肯定同意。更新。+1为他们指明了应该走的方向,而不是他们要求走的路。人们需要解决就业问题;有时更换工具是解决问题的方法。
parseSomething :: [String] -> (Maybe Something, [String])
parseSomething ("Something":strInt:stra:strb:rest) = 
  (Something <$> readMay strInt <*> pure stra <*> pure strb, rest)
parseSomething rest = (Nothing, rest)