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!
Related
This question already has answers here:
Haskell : Infinite list when integer is pushed to stack implementation
(2 answers)
ghci self-referencing assignment
(4 answers)
Closed 1 year ago.
I started to learn Haskell as a new language just because I can. As a practice I tried to code a simple BinTree but I'm running in a quite infuriating error.
This is the sourcecode I'm having trouble with:
data Tree = Node Tree Int Tree
| Empty
deriving (Eq,Show)
addNode :: Tree -> Int -> Tree
addNode Empty a = Node Empty a Empty
addNode (Node left a right) b | a > b = Node (addNode left b) a right
| a < b = Node left a (addNode right b)
| otherwise = Node left b right
Note: I tried running the code with GHC 8.10.7 and GHC 9.2.1 but to no avail.
The Problem happens as I'm trying to run addNode on an Empty binTree test.
Creating the empty binTree with test = Empty and checking it with just test works out fine and gives me Empty as an result, but if I then try to add a node to test with test = addNode test <Int> and try to show me the result of test nothing happens. The compiler is trying to run the code, but it just freezes and I have to reopen PowerShell.
If it helps, this is my current setup:
GHC 9.2.1 | 8.10.7
cabal 3.6.2.0
HLS 1.5.1
Stack 2.7.3
OS Win10
By running test = addNode test 5, you weel keep adding 5 for an infinite amount of times. It does not take the "old" test. In Haskell a variable is always immutable, if you use test in the "body" of the definition, then it will use the variable you are defining. It works thus as a recursive let statement [wiki].
Here it thus means that you define test as:
let test be the result of adding <Int> to test.
and this will thus result in trying to add that integer value for an infinite amount of times, since it means test is adding <Int> to a tree that has add <Int> that has added <Int> that …
You can define a new variable and use the old tree with:
test2 = addNode test 5
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.
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
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.
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