简体   繁体   English

从元组列表中获取第一个元素

[英]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种主要方式: typenewtypedataclass

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相同的内存,但在编译时MyIntInt不能互换使用。 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. 那么IntegerNode类型不同,反之亦然。 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.

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