# Function expects structure of newtype but not newtype itself

I seem to miss something fundamental.

When I try to map join with the sampleGraph I get this error:

Main> map join sampleGraph <interactive>:3:10: Couldn't match expected type ‘[(Start, [End])]’ with actual type ‘Graph’ In the second argument of ‘map’, namely ‘sampleGraph’ In the expression: map join sampleGraph

**This is the code**

type Node = Integer type Edge = (Node,Node) type Start = Node type End = Node newtype Graph = Graph [(Start,[End])] deriving (Eq,Show) join :: (Start, [End]) -> [Edge] join (start, ends) = map (\ e -> if start < e then (start, e) else (e, start)) ends sampleGraph = (Graph [(5,[1,2,3]), (7,[1,2]), (1,[1,2]), (2,[1,2]) ])

## Answers

The type of map is

map :: (a -> b) -> [a] -> [b]

In this case, join has type

join :: (Start, [End]) -> [Edge]

So map join has type

map join :: [(Start, [End])] -> [[Edge]]

And what we want is Graph -> [[Edge]]. So we need a function Graph -> [(Start, [End])] and we'll be all set. Fortunately, this is really simple with record accessors!

type Node = Integer type Edge = (Node, Node) type Start = Node type End = Node newtype Graph = Graph { edges :: [(Start, [End])] } deriving (Eq, Show) join :: (Start, [End]) -> [Edge] join (start, ends) = map (\e -> if start < e then (start, e) else (e, start)) ends sampleGraph = Graph [(5, [1, 2, 3]), (7, [1, 2]), (1, [1, 2]), (2, [1, 2]) ] foo = map join . edges

We declare an accessor edges for the edges field, and it's automatically given the type Graph -> (Start, [End]). Composing map join . edges yields the final desired type.

An alternate way of doing this would be to use a case-expression to destruct Graph into its constituent parts:

case sampleGraph of Graph edges -> map join edges

Life is a buffet of options.