【问题标题】:"Prelude.read: no parse", own data type“Prelude.read: no parse”,自己的数据类型
【发布时间】:2019-05-16 14:04:47
【问题描述】:

我正在尝试从文件中读取两个属于自己的数据类型“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.hs

    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)]]

【问题讨论】:

  • 嗯...你的拼图输入文件中有什么?
  • 感谢您提醒我这件事!在我的输入文件中,我有两个涵盖板边数据类型的长列表:[[(Field, Int)]]。它类似于: [[[(Black,2),(Yellow,2),(Black,1)],[(Black,2),(Yellow,1),(Black,3)]] [[[ (黑色,2),(黄色,2),(黑色,1)],[(黑色,2),(黄色,1),(黑色,3)]]
  • 这里有个提示:打开 GHCi 并尝试show 你的一些数据结构。您看到的是自动派生的read 所期望的格式。
  • 所以我现在尝试这样做,对于“显示字段”它说“数据构造函数不在范围内:字段 :: ()”而对于“显示 B.BoardEdge”它说“没有实例for (显示 ([[(B.Field, Int)]] -> B.BoardEdge))"。制作实例可以解决我的问题吗?
  • @ŁukaszNiewiński 您只能 show 您的数据类型的“完整”值。例如,BoardEdge 需要 colRow

标签: haskell haskell-prelude


【解决方案1】:

将您自己的代码 sn-ps 和 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

或者不那么狡猾:如果您希望默认的 read 实例解析您的输入,那么您的输入必须是正确的带有数据构造函数的 Haskell 代码等等。在这种情况下,需要使用 BoardEdge

【讨论】:

  • 伙计,非常感谢!你准确地向我展示了我所缺少的东西。我没想过使用“BoardEdge {colRow = [.....]}”。你的对比太棒了,谢谢! :)
猜你喜欢
  • 2020-01-31
  • 2017-09-28
  • 1970-01-01
  • 1970-01-01
  • 2015-04-18
  • 2020-09-11
  • 2011-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多