gpt4 book ai didi

list - Haskell 中 [String] 的模式匹配

转载 作者:行者123 更新时间:2023-12-03 12:28:30 26 4
gpt4 key购买 nike

我正在学习函数式编程的入门类(class),其中我们使用 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 将使用模式匹配来命名列表中的前两个字符串(行)和其余字符串。

但是我相信正在发生的事情是 finish 是列表中的顶部元素,并且 start 被分配了该字符串中的顶部字符。

我真的很想知道如何解决这个问题以及实际发生了什么。

非常感谢!

解析器.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)

类型.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)

最佳答案

您的变量 track 实际上是单行列表,而不是包含 '\n' 的字符串。由于您已经将其拆分为,因此您可以在其上map readLine,给出:

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

这里是 tracks::[String],这就是为什么你可以对它们全部进行 map readLine - 你不需要使用readLines 首先将它分成几行。 (你可以说这是一个列表,因为它是 : 右侧的最后一个东西。)

你说

However what I believe is happening is that finish is the top element from the list, and start gets assigned the top char from that string.

发生的事情是:因为你要求 readLines track 作为第一个输出,Haskell 从这里开始,并且因为你声明了

readLines :: String -> [Line]

这意味着 track 必须是一个字符串——这是 readLines 唯一可以处理的事情。

首先,你需要记住 : 左边是一个元素,右边是一个列表,所以在

3:4:stuff

stuff 必须是 [Integer] 因为它在一些 Integer 元素的右边。同样,

c:"a string"

意味着 c 必须是一个 Char,因为 String = [Char]。

在您的代码中,我们计算出 track 是一个字符串,所以这意味着当您编写

(start : finish : track)

start 和 finish 都必须是可以放在 String 前面的元素,因此 start 和 finish 都必须是 Char。

Haskell 然后查看您的代码 readPoint start,但是因为它已经确定 start 的类型为 Char,但是

readPoint :: String -> Point

它提示 Char 和 String 不匹配。

我认为您犯了错误,因为您忘记了 readLines 采用单个字符串,但(从名称上)感觉它应该愉快地采用字符串列表。您的 parseLines 看起来像做类似的事情,但它需要一个字符串列表,因此可以应对,而 readLines 需要一个带有换行符的字符串,因此无法处理列表。

关于list - Haskell 中 [String] 的模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12466964/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com