[英]Get First Elements From List Of Tuples
I have a List with this format [ (Int, [(Int, Int, Float)]) ]. 我有一个这种格式的列表[(Int,[(Int,Int,Float)])]。 Its a list of Nodes and their Edges on a graph.
它是一个图表上的节点及其边缘列表。 Each tuple of the list contains : (Node, [(startNode, endNode, Weight)]).
列表的每个元组包含:(Node,[(startNode,endNode,Weight)])。 What id like to do is create a list of all the Nodes.
我喜欢做的是创建所有节点的列表。 I've tried to this using:
我试过这个用过:
nodes xs = map fst xs
But it does not work and i have no clue why. 但它不起作用,我不知道为什么。 Any suggestions?
有什么建议么?
EDIT: To be more specific these are the data structures i am using 编辑:更具体地说,这些是我正在使用的数据结构
data Graph = G [(Node, [Edge])]
data Node = N Integer
type Edge = ( Node, Node, Float )
You need to unwrap the data from the Graph
data type to operate on it. 您需要从
Graph
数据类型中解包数据以对其进行操作。 The easiest way would be to do something like 最简单的方法就是做类似的事情
mapG :: ([(Node, [Edge])] -> a) -> Graph -> a
mapG f (G nodes) = map f nodes
Then you could just use it as 然后你可以用它作为
> let xs = G [(N 1, []), (N 2, [])]
> mapG fst xs
[N 1, N 2]
The type of Graph
is not a list, it's a wrapper around a list. Graph
的类型不是列表,它是列表的包装器。 You might instead consider just using a type alias since you aren't using any features of Haskell's data types, something more like 您可能会考虑仅使用类型别名,因为您没有使用Haskell数据类型的任何功能,更像是
type Edge = (Node, Node, Float)
type Node = Integer
type Graph = [(Node, [Edge])]
Then you can easily do 然后你可以轻松做到
> let xs = [(1, []), (2, [])] :: Graph
> :type xs
xs :: Graph
> map fst xs
[1, 2]
So, a quick overview of types in Haskell. 因此,快速浏览Haskell中的类型。 There are 4 main ways to declare something that can be used in a type signature:
type
, newtype
, data
, and class
. 声明可以在类型签名中使用的东西有4种主要方式:
type
, newtype
, data
和class
。
type
The easiest to understand, anything declared as a type
is simply an alias. 最容易理解的是,任何声明为
type
东西都只是一个别名。 So 所以
type Node = Integer
Is the exact same as Integer
itself. 与
Integer
本身完全相同。 It can be used anywhere Integer
is used, and vice-versa. 它可以在任何使用
Integer
地方使用,反之亦然。 All this construct is for is to make your intentions more clear, such as the pre-defined FilePath
type that is an alias for String
. 所有这些构造都是为了使您的意图更加清晰,例如预定义的
FilePath
类型,它是String
的别名。 If you see a function 如果你看到一个功能
writeToFile :: String -> String -> IO ()
compared to 相比
writeToFile :: FilePath -> String -> IO ()
You immediately know in the second one that the first argument is the file path without having to look at anything else. 你会立刻知道第二个参数是文件路径,而不必查看其他任何内容。 Types can also be used to make synonyms for more complex types, such as
类型也可用于为更复杂的类型创建同义词,例如
type Edge = (Node, Node, Float)
Now you can write Edge
everywhere you want this tuple, which is much more succinct and easy to understand. 现在你可以在任何你想要这个元组的地方编写
Edge
,它更加简洁易懂。 type
s can also be parameterized type
s也可以参数化
type List a = [a]
By using type
, you also get all the typeclass instances for what you're aliasing, so for example you can add two Node
s together with the usual +
and get back a Node
. 通过使用
type
,您还可以获得所有类型化的类型类实例,例如,您可以将两个Node
与常用的+
一起添加并返回一个Node
。
newtype
A slightly beefier version of type
, newtype
s have to follow a particular form. type
稍微强一些, newtype
必须遵循特定的形式。 They have a single constructor of a single type, and are usually used as an alias where you don't want people being able to really see what's inside. 它们只有一个单一类型的构造函数,通常用作别名,你不希望人们真正看到里面的东西。 For example:
例如:
newtype MyInt = MyInt Int
creates a type called MyInt
that contains a single value of type Int
. 创建一个名为
MyInt
的类型,它包含Int
类型的单个值。 This is (almost always) optimized away at compile time, so once the program runs MyInt
takes up the same memory as Int
, but at compile time MyInt
and Int
can not be used interchangeably. 这在编译时(几乎总是)优化掉,因此一旦程序运行,
MyInt
占用与Int
相同的内存,但在编译时MyInt
和Int
不能互换使用。 These become very useful later. 这些在以后变得非常有用。 Like
type
s, they can be parameterized, but unlike types you don't get instances for free. 与
type
s一样,它们可以参数化,但与类型不同,您不能免费获得实例。 MyInt
does not implement Num
by default, so you can't add them together. MyInt
默认不实现Num
,因此您无法将它们一起添加。
data
This is a very complex subject, so I'll gloss over a lot. 这是一个非常复杂的主题,所以我会说很多。 A
data
type is something entirely new, not just an alias. data
类型是全新的,而不仅仅是别名。 It can have 1 or more constructors that take 0 or more arguments each. 它可以有一个或多个构造函数,每个构造函数需要0个或多个参数。
Bool
is a data type that has 2 constructors, each with 0 arguments: Bool
是一个具有2个构造函数的数据类型,每个构造函数都有0个参数:
data Bool = False | True
Maybe
has two constructors, but one takes an argument: Maybe
有两个构造函数,但有一个需要参数:
data Maybe a = Nothing | Just a
And here we see that Maybe
is also parameterized. 在这里我们看到
Maybe
也参数化了。 These data
types also do not implement the typeclass instances of their contents, since in general this is impossible. 这些
data
类型也不实现其内容的类型类实例,因为通常这是不可能的。 You can also provide multiple parameters to data
types such as 您还可以为
data
类型提供多个参数,例如
data Either a b = Left a | Right b
If you had a data type like 如果您有类似的数据类型
data Node = N Integer
Then Integer
is not the same type as Node
, and vice-versa. 那么
Integer
与Node
类型不同,反之亦然。 In order to convert an Integer
into a Node
, you have to use the N
constructor. 要将
Integer
转换为Node
,必须使用N
构造函数。 You can think of constructors as a special kind of function, you can even ask for their types in GHCi: 您可以将构造函数视为一种特殊的函数,甚至可以在GHCi中询问它们的类型:
> :type Just
Just :: a -> Maybe a
class
This is the most abstract one. 这是最抽象的一个。 Typeclasses don't define a type directly, instead they provide a sort of prototype for what an instance of that typeclass would look like.
类型类没有直接定义类型,而是为类型类的实例提供了一种原型。 For example, the
Eq
typeclass is essentially defined as 例如,
Eq
类型类基本上定义为
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
a /= b = not (a == b)
Here Eq
says that a type that implements this class must provide a definition for the function (==)
, and can optionally provide a definition for (/=)
, but there is a default implementation in case you don't provide it. 这里
Eq
说实现这个类的类型必须提供函数的定义(==)
,并且可以选择为(/=)
提供定义,但是如果你不提供它,则有一个默认实现。 data Node
could implement this as data Node
可以实现这一点
instance Eq Node where
(N a) == (N b) = a == b
There is enough information, details, and extensions to the Haskell type system that you could fill a few books, so don't expect this to be comprehensive in any form. Haskell类型系统有足够的信息,细节和扩展,您可以填写几本书,所以不要指望它以任何形式全面。 There are entire topics that I didn't even mention, but this should be a good primer for you.
我甚至没有提到过整个主题,但这应该是一个很好的入门书。
As for generating edges, that's up to you. 至于生成边缘,这取决于你。 I don't know what your graph is being used for or what kind of data you expect to put in it, so I don't think I can really help you there.
我不知道您的图表用于什么或者您希望将哪种数据放入其中,因此我认为我无法真正帮助您。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.