Haskell graph data type representation - haskell

I want to represent a graph in Haskell in the following manner:
For each node I want to store it's value and a list of adjacent nodes. The problem which I'm having difficulties with is that I want the adjacent nodes to be stored as references to other nodes.
For example, I want node ny to be stored as („NY“ (l p)) where l and p are adjacent nodes,and not as („NY“ („London“ „Paris“)).
I tried something like this :
data Node a = Node { value :: a
, neighbors :: [Node a]
}deriving (Show)
let n1 = Node {value=1, neighbors=[n2]}
let n2 = Node {value=1, neighbors=[n1 n3]}
let n3 = Node {value=1, neighbors=[n2]}
But I get en error in let. What am I doing wrong ?

Two problems:
let is an expression form and at top level the compiler is expecting a declaration form.
You need a single nest of bindings; by using three lets, you've split the definitions into three separate scopes.
The following code compiles, and when I ask for n1, I get an infinite string printout as expected:
module Letnest
where
data Node a = Node { value :: a
, neighbors :: [Node a]
} deriving (Show)
n1 = Node {value=1, neighbors=[n2]}
n2 = Node {value=1, neighbors=[n1, n3]}
n3 = Node {value=1, neighbors=[n2]}

I wouldn't represent a graph this way. Store the nodes in a Map or an Array and refer to them by their keys instead of directly pointing to them. This would be much easier to save, load, maintain, and work with.
For some problems with your current representation:
Reid Barton commented:
Note that n1 and n3 are completely indistinguishable (since they have the same definition) which, depending on your application, may be a problem with this representation.
(there is no is comparison a la Python in Haskell)
Norman Ramsey noticed:
I get an infinite string printout

Related

how to access number value of tree node with Haskell

I'm going through a Haskell tutorial https://www.futurelearn.com/courses/functional-programming-haskell/9/steps/1103477 and this section is calling for a function that inserts a node to a binary tree. I'd like to add the constraint that the tree is a BST and as such would like to define my base case as something like "if the value to insert is less than the value at the leaf node, add a left node, else add a right node". There's a similar post here Adding a leaf to Binary Search Tree, Haskell but it appears to apply a technique that's yet to be introduced using the #. If trying to implement this, I'm struggling to find a way to access the number value of the leaf node. Also, I'm unsure as to which node I'd return. I'm tempted to return the point of insertion. Any help would be much appreciated.
The typedef of the method is as follows
data Tree = Leaf | Node Int Tree Tree deriving Show
insertNodeToBST :: Tree -> Int -> Tree
insertNodeToBST Leaf value =
if value < LeafValue
then (Node value (Node value null null) null)
else (Node value null (Node value null null))
Leafs have no value, so you cannot extract a value from them*. For Nodes, you can use pattern matching, as usual:
insertNodeToBST (Node valueInTree leftChild rightChild) value = ...
* This doesn't mean you're stuck if you see a Leaf. There is a canonical best answer for the right hand side of insertNodeToBST Leaf value = ... -- think about it!

How do fixpoint, variable, let and tag schema constructors work in Winery?

I had previously asked where the Winery types are indexed. I noticed that in the serialization for the schema for Bool, which is [4,6], the 4 is the version number, and 6 is the index of SBool in SchemaP. I verified the hypothesis using other "primitive" types like Integer (serialization: 16), Double (18), Text (20). Also, [Bool] will be SVector SBool, serialized to [4,2,6], which makes sense: the 2 is for SVector, the 6 is for SBool.
But SchemaP also contains constructors that I don't intuitively see how are used: SFix, SVar, STag and SLet. What are they, and which type would I need to construct the schema for, to see them used? Why is SLet at the end, but SFix at the beginning?
SFix looks like a µ quantifier for a recursive type. The type µx. T is the type T where x refers to the whole type µx. T. For example, a list data List a = Nil | Cons a (List a) can be represented as L(a) = µr. 1 + a × r, where the recursive occurrence of the type is replaced with the variable r. You could probably see this with a recursive user-defined type like data BinTree a = Leaf | Branch a (BinTree a) (BinTree a).
This encoding doesn’t explicitly include a variable name, because the next constructor SVar specifies that “SVar n refers to the nth innermost fixpoint”, where n is an Int in the synonym type Schema = SchemaP Int. This is a De Bruijn index. If you had some nested recursive types like µx. µy. … = SFix (SFix …), then the inner variable would be referenced as SVar 0 and the outer one as SVar 1 within the body …. This “relative” notation means you can freely reorganise terms without worrying about having to rename variables for capture-avoiding substitution.
SLet is a let binding, and since it’s specified as SLet !(SchemaP a) !(SchemaP a), I presume that SLet e1 e2 is akin to let x = e1 in e2, where the variable is again implicit. So I suspect this may be a deficiency of the docs, and SVar can also refer to Let-bound variables. I don’t know how they use this constructor, but it could be used to make sharing explicit in the schema.
Finally, STag appears to be a way to attach extra “tag” metadata within the schema, in some way that’s specific to the library.
The ordering of these constructors might be maintained for compatibility with earlier versions, so adding new constructors at the end would avoid disturbing the encoding, and I figure the STag and SLet constructors at the end were simply added later.

Need help storing the previous element of a list (Haskell)

I'm currently working on an assignment. I have a function called gamaTipo that converts the values of a tuple into a data type previously defined by my professor.
The problem is: in order for gamaTipo to work, it needs to receive some preceding element. gamaTipo is defined like this: gamaTipo :: Peca -> (Int,Int) -> Peca where Peca is the data type defined by my professor.
What I need to do is to create a funcion that takes a list of tuples and converts it into Peca data type. The part that im strugling with is taking the preceding element of the list. i.e : let's say we have a list [(1,2),(3,4)] where the first element of the list (1,2) always corresponds to Dirt Ramp (data type defined by professor). I have to create a function convert :: [(Int,Int)] -> [Peca] where in order to calculate the element (3,4) i need to first translate (1,2) into Peca, and use it as the previous element to translate (3,4)
Here's what I've tried so far:
updateTuple :: [(Int,Int)] -> [Peca]
updateTuple [] = []
updateTuple ((x,y):xs) = let previous = Dirt Ramp
in (gamaTipo previous (x,y)): updateTuple xs
Although I get no error messages with this code, the expected output isn't correct. I'm also sorry if it's not easy to understand what I'm asking, English isn't my native tongue and it's hard to express my self. Thank you in advance! :)
If I understand correctly, your program needs to have a basic structure something like this:
updateTuple :: [(Int, Int)] -> [Peca]
updateTuple = go initialValue
where
go prev (xy:xys) =
let next = getNextValue prev xy
in prev : (go next xys)
go prev [] = prev
Basically, what’s happening here is:
updateTuple is defined in terms of a helper function go. (Note that ‘helper function’ isn’t standard terminology, it’s just what I’ve decided to call it).
go has an extra argument, which is used to store the previous value.
The implementation of go can then make use of the previous value.
When go recurses, the recursive call can then pass the newly-calculated value as the new ‘previous value’.
This is a reasonably common pattern in Haskell: if a recursive function requires an extra argument, then a new function (often named go) can be defined which has that extra argument. Then the original function can be defined in terms of go.

Using Haskell sum type to make recursive lists - recursion anchor?

Trying to understand Haskell better, I want to build some recursive list structures using sum types.
These two types are unrelated, but in the same file:
data EList = EList {elem::Point, rest::EList} | Empty
data ETree = ENode {val:: Int, left::ETree, right::ETree} | Empty
So I get a "multiple declarations of 'Empty'" error. Reading this post, I understand that 'Empty' is not a keyword (as I assumed when this data type was presented in class).
If I want to use n types like this in my program, I have to come up with n different names for the empty element, that doesn't seem right.
Is there a common expression to determine the end of the list?
Or should I just not be using this 'homemade' type?
Suppose that you were allowed to declare two datatypes with an Empty constructor, as you have done. Given the definition
x = Empty
what would be the type of x? It could be EList or ETree, but the computer can't know which one you meant. That's why in general, you're can't declare the same name more than once in a given file.
One simple solution is simply to use different names. Here I'm using Nil for the empty list and Leaf for the empty tree, as is conventional.
data List = Cons Point List | Nil
data Tree = Node Int Tree Tree | Leaf
(Aside: It's usually not a good idea to declare record fields in a sum type because it means the extractors will be partial functions.)
An alternative is to put your two overlapping names in different files.
List.hs:
module List where
data List = Cons Point List | Empty
Tree.hs:
module Tree where
data Tree = Node Int Tree Tree | Empty
Now, if you import both of these modules, referring to Empty is disallowed because once again the machine doesn't know which one you meant. But this time, you can sort it out yourself using qualified names.
import List
import Tree
emptyList = List.Empty
emptyTree = Tree.Empty

Graph function in Haskell

I have such a data type :
data Node a = Node
{ label :: a,
adjacent :: [(a,Int)] } deriving Show
Example : ( Node 'a' [ ( 'b' , 3 ) , ( 'c' ,2 ) ] )
I want to get the label from this structure, I wrote this function (and several other combinations which I thought might work) :
giveLabel Node a [(c,b)] = a;
But I keep getting errors. Can you tell me how should I change my function? Thanks
giveLabel (Node a [(c,b)]) = a
Is the syntax you want - defining functions uses the same rules of precedence as calling them, and according to those rules, you defined a function giveLabel with three arguments (Node, a, and [c,b]); and that was illegal because in that context Node was missing arguments.
Even that probably isn't what you want - the pattern [(c,b)] only matches lists with exactly one item in. Since you don't care about the list of neighbours you can write:
giveLabel (Node a xs) = a
...where xs will bind to the whole list of neighbours; but actually since you don't even care about that, you can write:
giveLabel (Node a _) = a
...where _ is a useful way of pattern matching against a parameter you aren't going to use.

Resources