haskell - “Prelude.read: no parse”,自己的数据类型
问题描述
我正在尝试从文件中读取两个自己的数据类型“BoardEdge”的列表。当我尝试运行代码时,出现异常:
“Main.hs:Prelude.read:没有解析”
正如我怀疑我在负责验证输入(validateInput)的函数上得到这个。当我在 ghci 中尝试插入两个 BoardEdge“对象”时,它运行良好并给出了 True。
谁能给我建议我做错了什么以及如何解决问题?
数据类型:
data Field = Empty | Black | Yellow deriving (Eq, Ord, Enum, Show, Read)
data BoardEdge = BoardEdge { colRow :: [[(Field, Int)]]} deriving (Read, Eq, Ord, Show)
主文件
main :: IO()
main = do
args <- getArgs
input <- loadInput args
putStrLn "Puzzle input loaded:"
putStrLn input
let parsedInput = parseInput input
if (validateInput parsedInput)
then putStrLn "Input is valid."
else error "Input invalid!"
-- asks for path and reads input file
loadInput :: [String] -> IO String
loadInput [] = getPath >>= readFile where
getPath = do
putStrLn "Provide path to puzzle input file:"
getLine
loadDefinition (a:_) = readFile a
-- get valid data from input file
parseInput :: String -> (B.BoardEdge,B.BoardEdge)
parseInput d = parseInput' $ lines d where
parseInput' (columns: rows :_) =
(read columns, read rows)
Board.hs 中的验证函数导入合格为 B:
validateInput :: (B.BoardEdge,B.BoardEdge) -> Bool
validateInput (columns, rows) = rowColEq where
rowColEq = countBlocks columns == countBlocks rows
-- function that counts total quantity of colored blocks
countBlocks :: (B.BoardEdge)-> Int
countBlocks (B.BoardEdge colRow) = countBlocks' $ concat colRow where
countBlocks' [] = 0
countBlocks' (x:xs) = snd x + countBlocks' xs
我的输入文件是这样的:
[[(Black,2),(Yellow,2),(Black,1)],[(Black,2),(Yellow,1),(Black,3)]]
[[(Black,5)],[(Black,2),(Black,1)],[(Black,2),(Black,2)],[(Black,1),(Black,2)]]
解决方案
将您自己的代码片段和 Fyodor 的评论粘合在一起:
Prelude> data Field = Empty | Black | Yellow deriving (Eq, Ord, Enum, Show, Read)
Prelude> data BoardEdge = BoardEdge { colRow :: [[(Field, Int)]]} deriving (Read, Eq, Ord, Show)
Prelude> let edge1 = BoardEdge [[(Black,2),(Yellow,2),(Black,1)],[(Black,2),(Yellow,1),(Black,3)]]
Prelude> show edge1
"BoardEdge {colRow = [[(Black,2),(Yellow,2),(Black,1)],[(Black,2),(Yellow,1),(Black,3)]]}"
Prelude> let correctInput = it -- ^^ the above
所以现在我们知道read
期望什么,show
产生什么。这与您用作输入的内容相比如何?
Prelude> let myInput = "[[(Black,2),(Yellow,2),(Black,1)],[(Black,2),(Yellow,1),(Black,3)]]"
Prelude> correctInput == myInput
False
Or less snarky: If you want default read
instances to parse your input then your input must be correct Haskell code with data constructors and all. In this case using BoardEdge
was needed.
推荐阅读
- heroku - Heroku CLI psql 命令不再有效
- outlook - 在 UTC 中创建事件 - 房间在用户的 TZ 中没有响应
- amazon-web-services - 在 DynamoDB 中聚合符合我们访问模式的数据
- image - 如何用值/文本替换 Gimp 中的粗线?
- java - Java:如何在特定时间后“打破”开关盒?
- java - 基于 IPv6 的 Android Things UDP 套接字
- bash - 检查变量是否包含特定的文本字符串 bash
- smooch - 如何在 Smooch 中阻止用户 - 垃圾邮件发送者
- r - 使用“滚动”组进行分组后总结
- soap - 使用类自定义来解决 java WSIMPORT 中的这种冲突