当前位置: 首页 > 知识库问答 >
问题:

Haskell中[String]的模式匹配

东郭展
2023-03-14

我正在学习函数式编程的入门课程,其中我们使用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)

共有2个答案

费星晖
2023-03-14

UPD。哦,对不起,我没有理解曲目意味着多个曲目,必须是[String]类型。因此,AndrewC的答案更合适

因为在haskell中,模式(x:xs)意味着如果x有类型a,那么xs必须是类型[a]你在parseTrack中的模式意味着类似于(a:a])的类型
编译器要计算类型a,首先在右边看到的是读线磁道。FuncreadLines具有类型字符串-

parseTrack (start : finish : track : _)

徐卓
2023-03-14

变量track实际上是一个单行列表,而不是一个包含'\n's的字符串。由于您已经将其拆分,因此您可以将readLine映射到它上面,给出:

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

这里的跟踪:: [String],这就是为什么您可以将映射readLine放在它们上面-您不需要使用readLines将其首先拆分为行。(你可以看出这是一个列表,因为它是右手边的最后一件事。)

你说

然而,我认为正在发生的是finish是列表中的顶部元素,start从该字符串中被分配了顶部字符。

发生的事情是:因为您要求将readLines跟踪作为第一个输出,Haskell从那里开始,并且由于您声明

readLines :: String -> [Line]

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

首先,您需要记住,左侧有一个元素,右侧有一个列表,因此

3:4:stuff

东西必须是[整数],因为它在某些整数元素的右侧。同样,

c:"a string"

表示c必须是字符,因为字符串=[Char]。

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

(start : finish : track)

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

Haskell然后查看您的代码readPoint start,但是因为计算出start具有Char类型,但是

readPoint :: String -> Point

它抱怨Char和String不匹配。

我想你犯了这个错误,因为你忘记了readLines只需要一个字符串,但是它(从名字来看)应该很高兴地需要一个字符串列表。您的parseLines看起来做了类似的事情,但是它需要一个字符串列表,所以可以处理,而readLines需要一个带有换行符的字符串,所以不能处理列表。

 类似资料:
  • 假设我想在Haskell中用 错误:

  • 本文向大家介绍正则表达式模式匹配的String方法,包括了正则表达式模式匹配的String方法的使用技巧和注意事项,需要的朋友参考一下 在JavaScript代码中使用正则表达式进行模式匹配经常会用到String对象和RegExp对象的一些方法,例如replace、match、search等方法,以下是对一些方法使用的总结。 String对象中支持正则表达式有4种方法,分别是:search、rep

  • 我必须使函数:: [((String, String), Int)]- 这就是我提出的功能: 输出应该是一个元组列表,其中的字符串与元组x1中的inputWord以及整数x2成对出现 问题是我得到了我认为不应该存在的非详尽模式。 我试图替换与 这使得非穷举模式在列表不为空时消失,但也阻止了函数遍历元组的最后一个元组。

  • 我试图编写函数尾部,它将字符串转换成字符串列表,方式如下: 以下是我的实现: 正如标题所暗示的,这个函数中有一些非详尽的模式。不幸的是,我不明白为什么。 我是哈斯克尔的新手。。。任何帮助都将不胜感激!

  • 问题内容: 我有以下输入, 我想提取所有输入, 除了 包含“ ”的行和包含单个(点)的最后一行。也就是说,我想提取以下内容 我尝试了以下方法 但它不起作用,因为它不会产生任何输出。 问题答案: 实际操作: 别忘了负前瞻,否则您将无法获得任何匹配;-)

  • 我正在编写一个Rust程序来收集每个输入行的第一个字,这有点类似于Unix实用程序。 这让我 我读过《不能作为可变借来》一书,因为它也是作为不可变借来的,但我仍然感到困惑:可变借来发生在第10行,而不可变借来发生在第12行,那么“已经作为不可变借来的变量是作为可变借来的”怎么可能发生呢?至少错误应该是“一个已经作为可变(在第10行)借用的变量被作为不可变(在第12行)借用”。