4

Haskell を使用する関数型プログラミングの入門コースを受講しています。演習の一部は、入力文字列のパーサーを作成することです。

ただし、次のエラーを解決することも、実際に何が起こっているのかを理解することもできません。

Parser.hs:29:71:
Couldn't match expected type `String' with actual type `Char'
In the first argument of `readPoint', namely `start'
In the expression: readPoint start
In the expression:
  (readLines track, readPoint start, readLine finish)

エラーは次の行から発生します。

readTrack str = parseTrack (lines str) where
    parseTrack (start : finish : track) = (readLines track, readPoint start, readLine finish)

私が予想していたのは、入力文字列が行のリストに分割され、それが parseTrack に渡されることです。次に、parseTrack はパターン マッチングを使用して、リストの上位 2 つの文字列 (行) と残りの文字列に名前を付けます。

しかし、私が信じているのは、finish がリストの一番上の要素であり、start がその文字列の一番上の char に割り当てられるということです。

この問題を解決する方法と、実際に何が起こっているのかを知りたいです。

どうもありがとう!

Parser.hs

module Parser where

import Types

readFloat :: String -> Float
readFloat str = case reads str of
    [] -> error "not a floating point number"
    (p,_):_ -> p

readInt :: String -> Int
readInt str = case reads str of
    [] -> error "not an integer"
    (p,_):_ -> p

readPoint :: String -> Point
readPoint str = parsePoint (words str) where
    parsePoint (x : y : _) = (readInt x, readInt y)

readLine :: String -> Line
readLine str = parseLine (words str) where
    parseLine (x1 : y1 : x2 : y2 : _) = ((readInt x1, readInt y1), (readInt x2, readInt y2))

readLines :: String -> [Line]
readLines str = parseLines (lines str) where
    parseLines (line : rest) = readLine line : parseLines rest

readTrack :: String -> Track
readTrack str = parseTrack (lines str) where
    parseTrack (start : finish : track) = (readLines track, readPoint start, readLine finish)

Types.hs

module Types where

type Vector2D   = (Int, Int)
type Point      =  Vector2D
type Line       = (Point, Point)
type Velocity   =  Vector2D

type CarState   = (Position, Velocity)
type Position   =  Vector2D
type Trace      = [Position]

type Track      = ([Line], Point, Line)
4

2 に答える 2

8

あなたの変数trackは、実際には s を含む文字列ではなく、単一行のリストでし'\n'た。すでに に分割しているので、次のようにして、それを上書きlinesできます。map readLine

readTrack str = parseTrack (lines str) where
    parseTrack (start:finish:tracks) 
                     = (map readLine tracks, readPoint start, readLine finish)

Here tracks :: [String]、これがすべてを実行できる理由です-最初に行に分割するためにmap readLineを使用する必要はありません。readLines( a の右側の最後のものなので、リストであることがわかります:。)

あなたは言う

しかし、私が信じていることは、finish がリストの一番上の要素であり、start がその文字列の一番上の char に割り当てられるということです。

何が起こっていたのか:readLines track最初の出力として要求したため、Haskell がそこから開始され、宣言してから

readLines :: String -> [Line]

これは文字列でなければならないことを意味してtrackいました - readLines が扱えるのはそれだけです。

:まず、左側に要素があり、右側にリストがあることを覚えておく必要があります。

3:4:stuff

stuff[Integer]一部の整数要素の右側にあるためです。同様に、

c:"a string"

String = [Char] であるため、c は Char でなければならないことを意味します。

あなたのコードではtrack、それが文字列であることがわかりました。

(start : finish : track)

start と finish の両方を String の前に配置できる要素にする必要があるため、start と finish の両方を Char にする必要があります。

次に、Haskell はあなたのコードを調べますが、Char 型readPoint startを持つことが判明したため、start

readPoint :: String -> Point

Char と String が一致しないと文句を言います。

readLines が 1 つの文字列を受け取ることを忘れていたため、間違いを犯したと思いますが、(名前から) 文字列のリストを喜んで受け取るべきだと感じました。あなたの parseLines は同様のことをしているように見えますが、文字列のリストを取るので対応しますが、 readLines は改行文字を含む単一の文字列を取るため、リストに対応できません。

于 2012-09-17T21:38:38.217 に答える
0

UPDtrackああ、すみません、それが複数のトラックを意味し、タイプでなければならないことがわかりませんでした[String]。したがって、AndrewC からの回答はより適切です。

haskell では、パターンは、タイプがある場合、あなたのパターンはのようなタイプを意味するタイプで(x:xs)なければならないことを意味します。 コンパイラは型を評価したいと考えており、最初に右側に表示されるのは. Funcには typeがあるので、コンパイラにはas which means is of type があります。haskellでもそうです。 しかし、あなたはとして必要です。したがって、最初の 3 つの文字列を取り、 の残りの末尾を捨てるだけです。タイプでは、 のような意味になります。そのために、一致するパターンを次のように書き換えることができます。xaxs[a]parseTrack(a : a : [a])
areadLines trackreadLinesString -> [Line]trackString[a]StringString[Char]aChar
aString[String](String : String : String : [String])parseTrack

parseTrack (start : finish : track : _)
于 2012-09-17T21:33:43.163 に答える