How can I build a recursive tree with concrete data types in Haskell? - haskell

I'd like to build a tree in Haskell where each node has a concrete data type. Ultimately I want to build and use my own, more complicated types, but I can't quite figure out how to get the toy example below to work.
I'd like to create a tree of Integers, starting with a large value at the trunk, getting smaller as you traverse down to the leaves.
data Tree x = Empty | Node x (Tree x) (Tree x) deriving (Show, Read, Eq)
copyBox :: Int -> Tree x
copyBox x
| x <= 0 = Node x Empty Empty
| x > 0 = Node x (copyBox (x-1)) (copyBox (x-1))
I would expect to be able to build a small tree like this:
let newtree = copyBox 3
ghci throws an error "Couldn't match expected type 'x' with actual type 'Int'" at line 5.
If I replace the function declaration above with the more general version below, there is no problem:
copyBox :: (Ord x, Num x) => x -> Tree x
Why isn't the type of x just "Int" in both cases?

copyBox :: Int -> Tree x promises to return a Tree of any type at all, at the caller's whim. So I can write copyBox 5 :: Tree String, which is a legal call based on your type signature. But of course this will fail: you're putting x in the Nodes; and you're trying to subtract 1 from it, which only works if it's a numeric type; and you're comparing it to 0, which only works if it's an ordered type...
You probably just intend copyBox :: Int -> Tree Int, since you are clearly only building a Tree with Int values in it.

Related

How to Access Fields of Custom Data Types without Record Syntax in Haskell?

I'd like to understand how to access fields of custom data types without using the record syntax. In LYAH it is proposed to do it like this:
-- Example
data Person = Subject String String Int Float String String deriving (Show)
guy = Subject "Buddy" "Finklestein" 43 184.2 "526-2928" "Chocolate"
firstName :: Person -> String
firstName (Subject firstname _ _ _ _ _) = firstname
I tried applying this way of accessing data by getting the value of a node of a BST:
data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)
singleton :: a -> Tree a
singleton x = Node x EmptyTree EmptyTree
treeInsert :: (Ord a) => a -> Tree a -> Tree a
treeInsert x EmptyTree = singleton x
treeInsert x (Node a left right)
| x == a = Node x left right
| x < a = Node a (treeInsert x left) right
| x > a = Node a left (treeInsert x right)
getValue :: Tree -> a
getValue (Node a _ _) = a
But I got the following error:
Could someone explain how to access the field correctly without using the record syntax and what the error message means? Please note that I'm a beginner in Haskell. My purpose is to understand why this particular case throws an error and how to do it it correctly. I'm not asking this to be pointed to more convenient ways of accessing fields (like the record syntax). If someone asked a similar question before: Sorry! I really tried finding an answer here but could not. Any help is appreciated!
You forgot to add the type parameter to Tree in your function's type signature
getValue :: Tree -> a
should be
getValue :: Tree a -> a
Expecting one more argument to `Tree'
means that Tree in the type signature is expecting a type argument, but wasn't provided one
Expected a type, but Tree has a kind `* -> *'
Tree a is a type, but Tree isn't (?) because it is expecting a type argument.
A kind is like a type signature for a type.
A kind of * means the type constructor does not expect any type of argument.
data Tree = EmptyTree | Tree Int Tree Tree
has a kind of *
It is like the type signature of a no-argument function (technically this is not really called a function, I think)
f :: Tree Int
f = Node 0 EmptyTree EmptyTree
A kind of * -> * means the type constructor expects an argument.
Your Tree type has a kind of * -> *, because it takes one type argument, the a on the left hand side of =.
A kind of * -> * is sort of like a function that takes one argument:
f :: Int -> Tree Int
f x = Node x EmptyTree EmptyTree

How might I be able to write multiple function definitions for multiple types in a polymorphic manner in Haskell?

Given my type definitions:
data Tile = Revealed | Covered deriving (Eq, Show)
data MinePit = Clean | Unsafe deriving (Eq, Show)
data Flag = Flagged | Unflagged deriving (Eq, Show)
type Square = (Tile, MinePit, Flag)
type Board = [[Square]]
I created two functions:
createBoard generates a 2D list of tuples of values -- or a 'Board'. It initialises a list of dimension n*m all of the same value.
createBoard :: Int -> Int -> Board
createBoard 0 _ = [[]]
createBoard _ 0 = [[]]
createBoard 1 1 = [[(Covered, Clean, Unflagged)]]
createBoard n m = take n (repeat (take m (repeat (Covered, Clean, Unflagged))))
An example:
λ> createBoard 2 3
[[(Covered,Clean,Unflagged),(Covered,Clean,Unflagged),(Covered,Clean,Unflagged)],[(Covered,Clean,Unflagged),(Covered,Clean,Unflagged),(Covered,Clean,Unflagged)]]
A function defineIndices was defined for the purpose of an in order list of indices for Board(s) produced by createBoard.
defineIndices :: Int -> Int -> [[(Int,Int)]]
defineIndices n m = [[(i,j) | j <- [1..m]] | i <- [1..n]]
It behaves like:
λ> defineIndices 2 3
[[(1,1),(1,2),(1,3)],[(2,1),(2,2),(2,3)]]
From here, I have created a function to create a MapBoard, where the values of a particular Square could be looked up given its indicies.
type MapBoard = Map (Int, Int) Square
createMapBoard :: [[(Int,Int)]] -> [[Square]] -> MapBoard
createMapBoard indices squares = M.fromList $ zip (concat indices) (concat squares)
However, it seemed reasonable to me that I should also write a method in which I can create a MapBoard directly from a pair of Int(s), implementing my prior functions. This might look like:
createMapBoard2 :: Int -> Int -> MapBoard
createMapBoard2 n m = createMapBoard indices squares where
indices = defineIndices n m
squares = createBoard n m
However, I looked up as to whether it is possible achieve polymorphism in this situataion with createMapBoard, and have createMapBoard2 be instead createMapBoard. I discovered online that this is called Ad-Hoc Polymorphism, and one can do e.g.
class Square a where
square :: a -> a
instance Square Int where
square x = x * x
instance Square Float where
square x = x * x
Attempting to write something similar myself, the best I could come up with is the following:
class MyClass a b MapBoard where
createMapBoard :: a -> b -> MapBoard
instance createMapBoard [[(Int,Int)]] -> [[Square]] -> MapBoard where
createMapBoard indices squares = M.fromList $ zip (concat indices) (concat squares)
instance createMapBoard Int -> Int -> MapBoard where
createMapBoard n m = createMapBoard indices squares where
indices = defineIndices n m
squares = createBoard n m
Attempting to compile this results in a Compilation error:
src/minesweeper.hs:35:19-26: error: …
Unexpected type ‘MapBoard’
In the class declaration for ‘MyClass’
A class declaration should have form
class MyClass a b c where ...
|
Compilation failed.
λ>
I am confused as to why I am not allowed to use a non-algebraic type such as MapBoard in the class definition.
class MyClass a b MapBoard where
Replacing MapBoard with another algebraic type c brings about another compilation error, which is lost on me.
src/minesweeper.hs:37:10-63: error: …
Illegal class instance: ‘createMapBoard [[(Int, Int)]]
-> [[Square]] -> MapBoard’
Class instances must be of the form
context => C ty_1 ... ty_n
where ‘C’ is a class
|
src/minesweeper.hs:39:10-46: error: …
Illegal class instance: ‘createMapBoard Int -> Int -> MapBoard’
Class instances must be of the form
context => C ty_1 ... ty_n
where ‘C’ is a class
|
Compilation failed.
Is it possible for me to achieve the ad-hoc polymorphism of createMapBoard? Am I able to create a class definition which has a strict constraint that the return type must be MapBoard for all instances?
Edit:
Having corrected the syntactic errors, my code is now:
class MyClass a b where
createMapBoard :: a -> b
instance createMapBoard [[(Int,Int)]] [[Square]] where
createMapBoard indices squares = M.fromList $ zip (concat indices) (concat squares)
instance createMapBoard Int Int where
createMapBoard n m = createMapBoard indices squares where
indices = defineIndices n m
squares = createBoard n m
This leads to yet another compilation error:
src/minesweeper.hs:37:10-23: error: …
Not in scope: type variable ‘createMapBoard’
|
src/minesweeper.hs:39:10-23: error: …
Not in scope: type variable ‘createMapBoard’
|
Compilation failed.
I am inclined to believe that an error in my understanding of classes is still present.
You want to write it this way:
class MyClass a b where createMapBoard :: a -> b -> MapBoard
instance MyClass [[(Int,Int)]] [[Square]] where
createMapBoard indices squares = M.fromList $ zip ...
instance MyClass Int Int where
createMapBoard n m = createMapBoard indices squares where
...
The ... -> ... -> MapBoard is already in the createMapBoard method's signature, this doesn't belong in the class / instance heads.
Incidentally, I'm not convinced that it really makes sense to have a class here at all. There's nothing wrong with having two separately named createMapBoard functions. A class only is the way to go if you can actually write polymorphic functions over it, but in this case I doubt it – you'd rather have either the concrete situation where you need the one version, or the other. There's no need for a class then, just hard-write which version it is you want.
One reason for rather going with separate functions than a class method is that it makes the type checker's work easier. As soon as the arguments of createMapBoard are polymorphic, they could potentially have any type (at least as far as the type checker is concerned). So you can only call it with arguments whose type is fully determined elsewhere. Now, in other programming languages the type of values you might want to pass is generally fixed anyway, but in Haskell it's actually extremely common to have also polymorphic values. The simplest example is number literals – they don't have type Int or so, but Num a => a.
I personally find “reverse polymorphism” normally nicer to work with than “forward polymorphism”: don't make the arguments to functions polymorphic, but rather the results. This way, it's enough to have the outermost type of an expression fixed by the environment, and automatically all the subexpressions are inferred by the type checker. The other way around, you have to have all the individual expressions' types fixed, and the compiler can infer the final result type... which is hardly useful because you probably want to fix that by a signature anyway.

Attempting to construct trees in Haskell

I am trying to use an unfold function to build trees.
Tree t = Leaf | Node (Tree t) t (Tree t)
unfoldT :: (b -> Maybe (b, a, b)) -> b -> Tree a
unfoldT f b =
case f b of
Nothing -> Leaf
Just (lt, x, rt) -> Node (unfoldT f lt) x (unfoldT f rt)
The build function needs to create a tree that has a height equal to the number provided, as well as be numbered in an in-order fashion. The base case being build 0 = Leaf and the next being build 1 = Node (Leaf 0 Leaf).
build :: Integer -> Tree Integer
My attempt at solving it:
build n = unfoldT (\x -> Just x) [0..2^n-2]
I am not entirely sure how to go about constructing the tree here.
Would love it if somebody could point me in the right direction.
Edit 1:
If I was to use a 2-tuple, what would I combine? I need to be able to refer to the current node, its left subtree and its right subtree somehow right?
If I was to use a 2-tuple, what would I combine?
I would recommend to pass the remaining depth as well as the offset from the left:
build = unfoldT level . (0,)
where
level (_, 0) = Nothing
level (o, n) = let mid = 2^(n-1)
in ((o, n-1), o+mid-1, (o+mid, n-1))
If I was to use a 2-tuple, what would I combine?
That's the key question behind the state-passing paradigm in functional programming, expressed also with the State Monad. We won't be dealing with the latter here, but maybe use the former.
But before that, do we really need to generate all the numbers in a list, and then work off that list? Don't we know in advance what are the numbers we'll be working with?
Of course we do, because the tree we're building is totally balanced and fully populated.
So if we have a function like
-- build2 (depth, startNum)
build2 :: (Int, Int) -> Tree Int
we can use it just the same to construct both halves of e.g. the build [0..14] tree:
build [0..14] == build2 (4,0) == Node (build2 (3,0)) 7 (build2 (3,8))
Right?
But if we didn't want to mess with the direct calculations of all the numbers involved, we could arrange for the aforementioned state-passing, with the twist to build2's interface:
-- depth, startNum tree, nextNum
build3 :: (Int, Int) -> (Tree Int, Int)
and use it like
build :: Int -> Tree Int -- correct!
build depth = build3 (depth, 0) -- intentionally incorrect
build3 :: (Int, Int) -> (Tree Int, Int) -- correct!
build3 (depth, start) = Node lt n rt -- intentionally incorrect
where
(lt, n) = build3 (depth-1, start) -- n is returned
(rt, m) = build3 (depth-1, n+1) -- and used, next
You will need to tweak the above to make all the pieces fit together (follow the types!), implementing the missing pieces of course and taking care of the corner / base cases.
Formulating this as an unfold would be the next step.

Haskell type checking in code

Could you please show me how can I check if type of func is Tree or not, in code not in command page?
data Tree = Leaf Float | Gate [Char] Tree Tree deriving (Show, Eq, Ord)
func a = Leaf a
Well, there are a few answers, which zigzag in their answers to "is this possible".
You could ask ghci
ghci> :t func
func :: Float -> Tree
which tells you the type.
But you said in your comment that you are wanting to write
if func == Tree then 0 else 1
which is not possible. In particular, you can't write any function like
isTree :: a -> Bool
isTree x = if x :: Tree then True else False
because it would violate parametericity, which is a neat property that all polymorphic functions in Haskell have, which is explored in the paper Theorems for Free.
But you can write such a function with some simple generic mechanisms that have popped up; essentially, if you want to know the type of something at runtime, it needs to have a Typeable constraint (from the module Data.Typeable). Almost every type is Typeable -- we just use the constraint to indicate the violation of parametericity and to indicate to the compiler that it needs to pass runtime type information.
import Data.Typeable
import Data.Maybe (isJust)
data Tree = Leaf Float | ...
deriving (Typeable) -- we need Trees to be typeable for this to work
isTree :: (Typeable a) => a -> Bool
isTree x = isJust (cast x :: Maybe Tree)
But from my experience, you probably don't actually need to ask this question. In Haskell this question is a lot less necessary than in other languages. But I can't be sure unless I know what you are trying to accomplish by asking.
Here's how to determine what the type of a binding is in Haskell: take something like f a1 a2 a3 ... an = someExpression and turn it into f = \a1 -> \a2 -> \a3 -> ... \an -> someExpression. Then find the type of the expression on the right hand side.
To find the type of an expression, simply add a SomeType -> for each lambda, where SomeType is whatever the appropriate type of the bound variable is. Then use the known types in the remaining (lambda-less) expression to find its actual type.
For your example: func a = Leaf a turns into func = \a -> Leaf a. Now to find the type of \a -> Leaf a, we add a SomeType -> for the lambda, where SomeType is Float in this case. (because Leaf :: Float -> Tree, so if Leaf is applied to a, then a :: Float) This gives us Float -> ???
Now we find the type of the lambda-less expression Leaf (a :: Float), which is Tree because Leaf :: Float -> Tree. Now we can add substitute Tree for ??? to get Float -> Tree, the actual type of func.
As you can see, we did that all by just looking at the source code. This means that no matter what, func will always have that type, so there is no need to check whether or not it does. In fact, the compiler will throw out all information about the type of func when it compiles your code, and your code will still work properly because of type-checking. (The caveat to this (Typeable) is pointed out in the other answer)
TL;DR: Haskell is statically typed, so func always has the type Float -> Tree, so asking how to check whether that is true doesn't make sense.

confused about the type of the Instance of a binary tree data type of Int Nodes in Haskell

I made a binary tree data type in Haskell, according to this code:
data Tree a = EmptyTree
| Node a
(Tree a) (Tree a) deriving (Show,Eq)
and I also created a function to insert elements in the tree:
treeinsert :: (Ord a) => a -> Tree a -> Tree a
treeinsert x EmptyTree = leaf x
treeinsert x (Node a left right)
| x == a = Node x left right
| x < a = Node a (treeinsert x left) right
| x > a = Node a left (treeinsert x right)
Now, for testing I am using a list of Int elements, like this:
ghci> let nums = [8,6,4,1,7,3,5]
ghci> let numsTree = foldr treeInsert EmptyTree nums
ghci> numsTree
Node 5 (Node 3 (Node 1 EmptyTree EmptyTree) (Node 4 EmptyTree EmptyTree)) (Node 7 (Node 6 EmptyTree EmptyTree) (Node 8 EmptyTree EmptyTree))
My question is when I check the type of numsTree:
:type numsTree
numsTree :: Tree Integer
Why doesn't it just have the type of "Tree"?
I am a little confused.
(sorry for my language)
You defined the type Tree as a parametrised type. The a after Tree in the data type's definition is this parameter. This means that there is not just one Tree type, but many different ones. For example, you can have a type Tree Integer containing integers, a type Tree Bool containing booleans and a type Tree (String -> String) containing functions from string to string.
Note that it's a good thing that you can distinguish these different types. It means that when you get a value out of such a tree, you know which type of value you're going to get. If there was just one Tree type, then you wouldn't be able to find out.
Why doesn't it just have the type of "Tree"?
Because you explicitly pass the list of numbers to it which restricts the type.
If you define nTree = foldr treeInsert(in ghci prepend a let) you get the expected more general type. By the way, you may want to add Leaf a as another data constructor.

Resources