从Haskell中的文本文件创建多边形列表

时间:2018-03-16 17:44:06

标签: list haskell

我已经阅读了一个数字文件,并从中创建了一个数字列表,现在我想根据列表中的数字创建一个多边形列表,因为它们具有特定的布局/模式。

type Point = (Double, Double)

data Polygon = Polygon { v :: Int
                       , y :: Int
                       , points :: [Point]  
                       }

main = do  
    let list = []
    handle <- openFile "polycake.in" ReadMode
    contents <- hGetContents handle
    let singlewords = words contents
        list = fileToList singlewords
        n = list!!0
        list' = drop 1 list
        polygons = polyList n list'  
    hClose handle 

fileToList :: [String] -> [Int]
fileToList = map read

polyList :: Int -> [Int] -> [Polygon]
polyList n [] = return []
polyList n list = do
    let v = list!!0
        y = list!!1
        list' = drop 2 list
        pointList = take (2*v) list'
        points = getPoints pointList
        list'' = drop (2*v) list'
        poly = Polygon { v = v, y = y, points = points}
        nextPoly = polyList (n-1) list''
    return (poly:nextPoly)

getPoints :: [Int] -> [Point]
getPoints (k:v:t) = (fromIntegral k, fromIntegral v) : getPoints t

但是我收到了错误:

polycake.hs:27:17: error:
     • Couldn't match type ‘[a0]’ with ‘Polygon’
      Expected type: [Polygon]
        Actual type: [[a0]]
     • In the expression: return []
      In an equation for ‘polyList’: polyList n [] = return []
   |
27 | polyList n [] = return []
   |                 ^^^^^^^^^

polycake.hs:37:5: error:
    • Couldn't match type ‘[Polygon]’ with ‘Polygon’
      Expected type: [Polygon]
        Actual type: [[Polygon]]
    • In a stmt of a 'do' block: return (poly : nextPoly)
      In the expression:
        do let v = list !! 0
               y = list !! 1
               ....
           return (poly : nextPoly)
      In an equation for ‘polyList’:
          polyList n list
            = do let v = ...
                     ....
                 return (poly : nextPoly)
   |
37 |     return (poly:nextPoly)
   |     ^^^^^^^^^^^^^^^^^^^^^^

我不确定为什么会收到这些错误。

样品polycake.in:

2
4 2
0 0
4 0
4 4
0 4
6 10
3 15
10 1
12 5
11 19
9 23
6 20

所以第一行是测试用例的#,每个测试用例以2个数字开头,第一个是顶点数,第二个是用于以后计算的y值。然后,以下v对是顶点或点。

1 个答案:

答案 0 :(得分:2)

您滥用do符号和return函数。 return不仅仅是指定函数返回值的关键字;它用于&#34;包裹&#34; monadic类型值内的值。虽然[]是monad,但您在函数中并没有这样使用它。

polyList :: Int -> [Int] -> [Polygon]
polyList n [] = []
polyList _ [x] = error "Too few points remaining"
polyList n (v:y:list') =
    let pointList = take (2*v) list' -- Note: list' may not *have* 2*v points
        points = getPoints pointList
        list'' = drop (2*v) list'
        poly = Polygon { v = v, y = y, points = points}
        nextPoly = polyList (n-1) list''
    in (poly:nextPoly)