I have this data type :
data Node a = Node
{ label :: a,
adjacent :: [(a,Int)] } deriving (Show, Eq)
data Network a = Graph [Node a] deriving (Show, Eq)
I have a function which turns a Graph to a list of nodes :
deGraph :: ([Node a] -> Network a) -> [Node a] -> [Node a]
deGraph _ x = x
for example :
Main> deGraph Graph [ ( Node 'a' [ ( 'b' , 3 ) , ( 'c' ,2 ) ] ) , ( Node 'b' [ ('c' , 3 ) ] ) , ( Node 'c' [] ) ]
[Node {label = 'a', adjacent = [('b',3),('c',2)]},Node {label = 'b', adjacent = [('c',3)]},Node {label = 'c', adjacent = []}]
But when I use the function inside a function like this :
func1 (Graph x) = deGraph (Graph x)
I get this error :
ERROR "./Network.hs":14 - Type error in application
* Expression : deGraph (Graph x)
Term : Graph x
Type : Network b
* Does not match : [Node a] -> Network a
Can you tell me how can I solve this problem?
Your deGraph function has two arguments and simply returns the second of the two.
You probably want this instead:
deGraph :: Network a -> [Node a]
deGraph (Graph x) = x
The call to deGraph in GHCi works because you forgot to put parentheses around Graph and the following list, so it's also a call with two arguments. In func1, you (correctly) use parentheses, but then get a type error, because you're inconsistent.
Simply make Graph a record, too:
data Network a = Graph { nodes :: [Node a] } deriving (Show, Eq)
Then nodes has type Network a -> [Node a], and can be called like
Main> nodes $ Graph listOfNodes
Related
I'm almost there with this code the only difference is instead to adding n1 to the graph, I have to add the edges of n1 to the graph but I can't seem to figure out how.
Question: The file includes a function named insertEdge of type Eq a =>
(NodeID,NodeID) -> Graph a -> Maybe (Graph a) that inserts an
edge from the Node with the given NodeID in the first part of the tuple
to the Node with the given NodeID in the second part of the tuple.
If the edge already exists, it should NOT introduce a duplicate. If
the nodes corresponding to either of the given NodeIDs do not already
exist, the function should return Nothing.
`insertEdge :: Eq a => (NodeID,NodeID) -> Graph a -> Maybe (Graph a)
insertEdge _ (Graph []) = Nothing
insertEdge (n1,n2) g#(Graph graph)
| not containsBothNodes = Nothing
| otherwise = Just(Graph(insertE (n1,n2) graph))
where
containsBothNodes :: Bool
containsBothNodes = case(lookupNode n1 g) of
(Just _)->True
_ -> False
insertE (n1,n2) ((n0,es):graph)=
if (getNodeID n0)==n2
then
if es/=[]
then (n0,es):graph
**else (n0,es++[n1]):graph**
else (n0,es):insertE (n1,n2)graph
Description of the graph
newtype Graph a = Graph [(Node a,[NodeID])]
deriving (Show,Eq)
type NodeID = Int
data Node a = Node { getNodeID :: NodeID,
getNodeVal :: a }
deriving (Show,Eq,Ord)
nodeA,nodeB,nodeC :: Node Char
nodeA = Node 0 'A'
nodeB = Node 1 'B'
nodeC = Node 2 'C'
exGraph :: Graph Char
exGraph = Graph [(nodeA,[1,2])
,(nodeB,[])
,(nodeC,[1,2])]
`
I highlighted the part that I cannot figure out. Instead of adding n1, it should add the edges of n1
I'm trying to insert a node to a graph. I already have a function to find the maximum nodeID so the new nodeID is 1 greater than it but I'm having trouble getting the output as a graph.
newID :: Maybe NodeID -> NodeID
newID Nothing = 1
newID (Just x) = x+1
insertNode :: a -> Graph a -> Graph a
insertNode v (Graph node_list)=
let newNode=Node(newID(maxNodeID (Graph node_list))) v
in (node_list): [[(newNode,[])]]
Description for the graph is:
newtype Graph a = Graph [(Node a,[NodeID])]
deriving (Show,Eq)
type NodeID = Int
data Node a = Node { getNodeID :: NodeID,
getNodeVal :: a }
deriving (Show,Eq,Ord)
nodeA,nodeB,nodeC :: Node Char
nodeA = Node 0 'A'
nodeB = Node 1 'B'
nodeC = Node 2 'C'
exGraph :: Graph Char
exGraph = Graph [(nodeA,[1,2])
,(nodeB,[])
,(nodeC,[1,2])]
I've been stuck for this for 2 hours now. I just want to insert the new node at the end of the graph.
You're almost there, the only things you have to change are:
Use (++) :: [a] -> [a] -> [a] instead of (:) :: a -> [a] -> [a]. The : operator is for inserting things at the front, for adding to the end of a list the simplest way is to use the form xs ++ [x].
Wrap the result in a Graph constructor.
So a working version is:
insertNode :: a -> Graph a -> Graph a
insertNode v (Graph node_list)=
let newNode=Node(newID(maxNodeID (Graph node_list))) v
in Graph (node_list ++ [(newNode,[])])
I am trying to get my feet wet with Haskell and I have found a few workshop which asks to create a graph data structure. I followed along and created a Binary Tree using map which felt much simpler. I have the following data types given
type Graph a = [(Node a, Edges)]
type Edges = [NodeID]
type NodeID = Int
data Node a = Node
{ getNodeID :: NodeID,
getNodeVal :: a
}
deriving (Show, Eq)
and example node would be as follows
nodeA = Node 0 'A'
and an example graph connected both ways would be
graphA = [(nodeA, [1]), nodeB, [0]]
Now in order to do any kind of insert or remove operation, I would first have to find out what the max NodeID at the moment is. So I am trying to write a maxNodeID as follows
maxNodeID :: Graph a -> Maybe NodeID
maxNodeID [] = Nothing --base case
But I am having a real hard coming up with the next case for this function.
My type definition for insertNode function is as follows
insertNode :: a -> Graph a -> Graph a
-- This is my idea for a base case but I get a parse error at 0
insertNode v [] = [a, []] where a = Node {0, v}
Any help with this and creating a insertNode function would be much appreciated as it would really help me set myself in the right path.
Rather than rolling my own, I would use the maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a functrion from Data.List.
maxNodeID :: Graph a -> Maybe NodeID
maxNodeID [] = Nothing --base case
maxNodeID xs = Just $ maximumBy (\a b -> compare (getID a) (getID b)) xs
where getID = getNodeID . fst
For your insertNode function you need
insertNode v [] = [(a, [])] where a = Node 0 v
-- or --
insertNode v [] = [(a, [])] where a = Node {getNodeID = 0, getNodeVal= v}
Edited to add:
If you are not comfortable with type classes yet, you can read the type of maximumBy specialized for Lists as :: (a -> a -> Ordering) -> [a] -> a.
I have these data types :
data Node a = Node
{ label :: a,
adjacent :: [(a,Int)] } deriving Show
data Network a = Graph [Node a] deriving Show
I want to turn a graph to a list of nodes. For example I want to turn this :
Graph [ ( Node 'a' [ ( 'b' , 3 ) , ( 'c' ,2 ) ] ) , ( Node 'b' [ ('c' , 3 ) ] ) , ( Node 'c' [] ) ]
to this :
[ ( Node 'a' [ ( 'b' , 3 ) , ( 'c' ,2 ) ] ) , ( Node 'b' [ ('c' , 3 ) ] ) , ( Node 'c' [] ) ]
I wrote this function and some other variations of it :
deGraph Graph [Node x y] = [Node x y]
but I kept getting erros. Can you tell me how I should change my function?
Thanks.
You're misunderstanding how to pattern match on a list.
foo [x] = x
matches a list of a single element and binds that element to x.
Since you want it to match on all lists, you'd do something like
foo xs = xs
so your code should change to
deGraph (Graph nodes) = nodes
-- Notice the fact that I wrapped the constructor
-- in parens
Wrap up:
Just to be explicit, here are the different ways you can match on a list
-- matches on individual elements (this is syntactic sugary goodness)
foo [x, y] = x
-- grabs the head and tail of the list (This is actual deconstructing)
foo (x:rest) = x
-- matches an empty list
foo [] = error "Oh noes"
-- matches everything
foo xs = head xs
Or any combination of the above.
Karva notation is used in Gene Expression Programming to represent mathematical expressions.
See here http://www.gene-expression-programming.com/Tutorial002.asp
You create an expression tree by reading the off the gene and filling in nodes from left to right, top to bottom.
So for example using the operators ( +, * ) and terminals (1,2,3,4,5,6) in "+*+1+2*3456" would evaluate to 39.
How would I do this in haskell using attoparsec (or parsec)?
karvaParser :: Parser Int
karvaParser = ????????????
Prelude> parse karvaParser "+*+1+2*3456"
Done 39
(I've proved this is a linear time algorithm in this answer to the question mentioned in the comments. There's a lengthier more hand-rolled solution in a previous revision of this answer.)
Gene Expression Programming: Karva notation.
There's probably a neat solution using the continuation passing monad, Cont, but I haven't thought of it. Here's a fairly clean pure functional solution to the problem. I'll take the opportunity to name drop some good general recursion schemes along the way.
Plan:
split the input into lists, one for each layer, using the total arity of the previous line. This is an anamorphism, i.e. grows a list from a seed ([]) and can be written using unfoldr :: (b -> Maybe (a, b)) -> b -> [a] or equivalently, unfoldr' :: (b -> (a, b)) -> (b -> Bool)-> b -> [a]
input: "Q/a*+b-cbabaccbac"
arities: 12022020000000000
output: ["Q","/","a*","+b","-c","ba"]
Recursively use splitAt to glue the children under the parent. This is a catamorphism, i.e. collapses a list down to a single (tree) value, and can be written using foldr :: (a -> b -> b) -> b -> [a] -> b
Combine the anamorphism and the catamorphism into one. That's called a hylomorphism.
These terms are introduced to the FP community in the seminal paper Functional Programming with Bananas, Lenses and Barbed wire.
Code
In case you're not familiar with it, Data.Tree supplies data Tree a = Node {rootLabel :: a, subForest :: Forest a} where type Forest a = [Tree a].
import Data.Tree
import Data.Tree.Pretty -- from the pretty-tree package
arity :: Char -> Int
arity c
| c `elem` "+*-/" = 2
| c `elem` "Q" = 1
| otherwise = 0
hylomorphism :: b -> (a -> b -> b) -> (c -> (a, c)) -> (c -> Bool) -> c -> b
hylomorphism base combine pullout stop seed = hylo seed where
hylo s | stop s = base
| otherwise = combine new (hylo s')
where (new,s') = pullout s
To pull out a level, we use the total arity from the previous level to find where to split off this new level, and pass on the total arity for this one ready for next time:
pullLevel :: (Int,String) -> (String,(Int,String))
pullLevel (n,cs) = (level,(total, cs')) where
(level, cs') = splitAt n cs
total = sum $ map arity level
To combine a level (as a String) with the level below (that's already a Forest), we just pull off the number of trees that each character needs.
combineLevel :: String -> Forest Char -> Forest Char
combineLevel "" [] = []
combineLevel (c:cs) levelBelow = Node c subforest : combineLevel cs theRest
where (subforest,theRest) = splitAt (arity c) levelBelow
Now we can parse the Karva using a hylomorphism. Note that we seed it with a total arity from outside the string of 1, since there's only one node at the root level. I've used the head function because that 1 causes the top level to be a list containing one tree.
karvaToTree :: String -> Tree Char
karvaToTree cs = let
zero (n,_) = n == 0
in head $ hylomorphism [] combineLevel pullLevel zero (1,cs)
Demo
Let's have a draw of the results (because Tree is so full of syntax it's hard to read the output!). You have to cabal install pretty-tree to get Data.Tree.Pretty.
see :: Tree Char -> IO ()
see = putStrLn.drawVerticalTree.fmap (:"")
ghci> arity '+'
2
ghci> pullLevel (3,"+a*bc/acb")
("+a*",(4,"bc/acb"))
ghci> combineLevel "a*" [Node 'b' [],Node 'c' []]
[Node {rootLabel = 'a', subForest = []},Node {rootLabel = '*', subForest = [Node {rootLabel = 'b', subForest = []},Node {rootLabel = 'c', subForest = []}]}]
ghci> see . Node '.' $ combineLevel "a*" [Node 'b' [],Node 'c' []]
.
|
---
/ \
a *
|
--
/ \
b c
ghci> karvaToTree "Q/a*+b-cbabaccbac"
Node {rootLabel = 'Q', subForest = [Node {rootLabel = '/', subForest = [Node {rootLabel = 'a', subForest = []},Node {rootLabel = '*', subForest = [Node {rootLabel = '+', subForest = [Node {rootLabel = '-', subForest = [Node {rootLabel = 'b', subForest = []},Node {rootLabel = 'a', subForest = []}]},Node {rootLabel = 'c', subForest = []}]},Node {rootLabel = 'b', subForest = []}]}]}]}
Which matches
as we see when we see it:
ghci> see $ karvaToTree "Q/a*+b-cbabaccbac"
Q
|
/
|
------
/ \
a *
|
-----
/ \
+ b
|
----
/ \
- c
|
--
/ \
b a
Eval
Once you have a Tree, it's easy to convert it to other things. Let's evaluate an expression in Karva notation:
action :: (Read num,Floating num) => Char -> [num] -> num
action c = case c of
'Q' -> sqrt.head
'+' -> sum
'*' -> product
'-' -> \[a,b] -> a - b
'/' -> \[a,b] -> a / b
v -> const (read (v:""))
eval :: (Read num,Floating num) => Tree Char -> num
eval (Node c subforest) = action c (map eval subforest)
ghci> see $ karvaToTree "Q+-*826/12"
Q
|
+
|
-------
/ \
- *
| |
-- ---
/ \ / \
8 2 6 /
|
--
/ \
1 2
ghci> eval $ karvaToTree "Q+-*826/12"
3.0