简体   繁体   English

Haskell 定义列表和列表理解

[英]Haskell Defining a List and List Comprehension

Good morning!早上好!

I am trying to define a list that takes in all possible Address types, which I have previously defined, and use list comprehension to do so.我正在尝试定义一个列表,该列表包含我之前定义的所有可能的地址类型,并使用列表理解来执行此操作。

Here's what I've got for earlier definitions that will likely be helpful for you to know:以下是我对早期定义的了解,可能对您有所帮助:

data Row = A | B | C | D | E | F | G | H | I | J deriving (Enum, Ord, Show, Bounded, Eq, Read)
data Column = One | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten  deriving (Enum, Ord, Show, Bounded, Eq, Read)
data Address = Address Row Column deriving (Show, Read, Eq)
data Cell = Cell Address Bool deriving (Show, Read, Eq)

I'm not sure if I need to be using Cell in this solution, but perhaps.我不确定是否需要在此解决方案中使用 Cell,但也许可以。

This is my current solution, and I'm wondering if anyone has suggestions on improving it, or perhaps it's just completely wrong.这是我目前的解决方案,我想知道是否有人对改进它有建议,或者它可能完全错误。 Any guidance would be appreciated!任何指导将不胜感激!

allAddressesA = [ x * y | x <- [Row] y <- [Column]]

And just for reference, here's a formal written requirement:仅供参考,这里有一个正式的书面要求:

Define allAddressesA as the list of all possible board Addresses.将 allAddressesA 定义为所有可能的板地址的列表。 Use a list comprehension that uses ranges of your Row and Column types.使用使用行和列类型范围的列表理解。

Thank you!谢谢! I'll be closely monitoring this so feel free to ask anything that you need clarified to help.我将密切关注此事,因此请随时提出任何您需要澄清的问题以提供帮助。 I appreciate you taking the time to read this and potentially offer advice :)感谢您花时间阅读本文并可能提供建议:)

You write:你写:

This is my current solution, and I'm wondering if anyone has suggestions on improving it, or perhaps it's just completely wrong.这是我目前的解决方案,我想知道是否有人对改进它有建议,或者它可能完全错误。

Whether it is completely wrong can be easily tested of course.是否完全错误当然可以很容易地测试。 Just type it in and ask your compiler:只需输入它并询问您的编译器:

allAddressesA = [ x * y | x <- [Row] y <- [Column]]

Mine says:我的 说:

parse error on input `<-'

I guess that qualifies as wrong.我想这是错误的。

So, let us first fix the syntax.因此,让我们首先修复语法。 The possibly multiple clauses in the second part of a list comprehension (the part after the | , that is) are to be separated by commas.列表推导式的第二部分(即|之后的部分)中可能有多个子句用逗号分隔。 Doing so gives:这样做给出:

allAddressesA = [ x * y | x <- [Row], y <- [Column]]

What does the compiler think of that?编译器对此有何看法?

Not in scope: data constructor `Row'
Not in scope: data constructor `Column'

Indeed, Row and Column are type constructors rather than data constructors.事实上, RowColumn是类型构造器而不是数据构造器。 That means that you can use them to build type expressions, but not to build "ordinary" value expressions.这意味着您可以使用它们来构建类型表达式,但不能构建“普通”值表达式。

Clearly, we are on the wrong path.显然,我们走在错误的道路上。 So let us take a few steps back.所以让我们退后几步。

Both your Row type and your Column type are in the type classes Enum and Bounded .你的Row类型和你的Column类型都在类型类EnumBounded Hence, we can easily produce lists with all row and column designators, respectively:因此,我们可以轻松地分别生成具有所有行和列指示符的列表:

allRows    = [minBound :: Row    .. maxBound]
allColumns = [minBound :: Column .. maxBound]

(Using minBound and maxBound makes your code somewhat more robust than immediately using A and J , and One and Ten , respectively, in the sense that adding constructors to Row and Column does not require you to change the definitions of allRows and allColumns .) (分别使用minBoundmaxBound使您的代码比立即使用AJ以及OneTen更健壮,因为向RowColumn添加构造函数不需要您更改allRowsallColumns的定义。)

In an interactive environment we can easily evaluate these lists.在交互式环境中,我们可以轻松评估这些列表。 Indeed, printing allRows gives:事实上,打印allRows给出:

> allRows
[A,B,C,D,E,F,G,H,I,J]

and for allColumns we get对于allColumns我们得到

> allColumns
[One,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten]

Now, as an address consists of a row and a column designator, generating all possible addresses simply reduces to taking the cross product of all rows and all columns.现在,由于地址由行和列指示符组成,因此生成所有可能的地址简单地简化为取所有行和所有列的叉积。 With the previous definitions for allRows and allColumns in place, we can easily write such a cross product as a list comprehension:有了之前对allRowsallColumns定义,我们可以轻松地编写这样的交叉产品作为列表allColumns

allAddresses = [Address row column | row <- allRows, column <- allColumns]

As you have 10 row designators and 10 column designators, you end up with a list of 10 x 10 = 100 addresses:由于您有 10 个行指示符和 10 个列指示符,您最终会得到一个 10 x 10 = 100 个地址的列表:

> length allAddresses
100

For amusement's sake, let us print the first 15:为了消遣,让我们打印前 15 个:

> take 15 allAddresses
[Address A One,Address A Two,Address A Three,Address A Four,Address A Five,
Address A Six,Address A Seven,Address A Eight,Address A Nine,Address A Ten,
Address B One,Address B Two,Address B Three,Address B Four,Address B Five]

Here's the skeleton for your code:这是您的代码的骨架:

allAddressesA = [ Address {- ... -} | x <- [A .. J], y <- [ {- ... -} ]]

replace each {- ... -} with the correct code.用正确的代码替换每个{- ... -}

data Address = Address Row Column

means that you get to create compound data of type Address , by using a constructor function named Address , which expects two arguments: first of type Row , and second of type Column .意味着您可以通过使用名为Address的构造函数来创建Address类型的复合数据,该函数需要两个参数:第一个参数为Row ,第二个参数为Column In specifying ranges, we show data elements, not types or course: we write [1 .. 10] , not [Int] .在指定范围时,我们显示数据元素,而不是类型或课程:我们写[1 .. 10] ,而不是[Int]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM