How to Access Fields of Custom Data Types without Record Syntax in Haskell? - 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

Related

Is it possible to create a function in Haskell that operates on a set of types?

I have been searching google for a while, but was not able to find an answer:
Say I have Tree ADT that is polymorphic, a base payload sum type and two extention sum types:
--Base.hs
data Tree a = Node a [Tree a] | Empty
data BasePayload = BaseA String | BaseB Int
--Extention1.hs
data Extention1 = Ext1A String String | Ext1B Int
--Extention2.hs
data Extention2 = B | A
I cannot modify the base type, and I do not know if and how many extention types are used at compile time. Is it possible to create functions that work like this:
--Base.hs
type GeneralTree = Tree SomeBoxType
transform :: Tree (SomeBoxType (any | BasePayload)) -> Tree (SomeBoxType any)
--Extention1.hs
transform :: Tree (SomeBoxType (any | Extention1)) -> Tree (SomeBoxType any)
--Extention2.hs
transform :: Tree (SomeBoxType (any | Extention2)) -> Tree (SomeBoxType any)
Is something like this possible? When I searched I found GADT, which is not what I need and DataKinds and TypeFamilies, which I did not understand 100%, but dont think will help here. Is that Row Polymorphism?
Thanks for your help.
I suspect you just want a Functor instance. Thus:
instance Functor Tree where
fmap f (Node x children) = Node (f x) (fmap (fmap f) children)
fmap f Empty = Empty
Now fmap can be given any of these types:
fmap :: (Either any BasePayload -> any) -> Tree (Either any BasePayload) -> Tree any
fmap :: (Either any Extention1 -> any) -> Tree (Either any Extention1 ) -> Tree any
fmap :: (Either any Extention2 -> any) -> Tree (Either any Extention2 ) -> Tree any
As an aside, I find the Empty constructor very suspicious. What's the difference between Node 0 [] and Node 0 [Empty] for example? Is Node 0 [Empty, Empty] a sensible value to have at all? Consider using Data.Tree, which comes with your compiler, doesn't have this issue, and already has a Functor instance.

'Cannot find "show" function' error when parameter is instance of Show

The following error is triggered:
ERROR - Cannot find "show" function for:
*** Expression : debugFunction getDebugTree
*** Of type : Tree (Tree Int) -> Bool
when running debugFunction getDebugTree
data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Eq, Show)
getDebugTree :: Tree Int
getDebugTree = (Node 1 (Empty) (Node 2 Empty Empty))
debugFunction :: Show a => a -> Tree a -> Bool
debugFunction _ _ = True
I've read that
reverse []
ERROR: Cannot find "show" function for:
* expression : reverse []
* of type : [a]
The top-level system for Hugs can only print values which belong to a
type which can be shown, that is a type which belongs to the Show
class. Now, the list type is an instance of Show, so what is wrong
with reverse [] (which evaluates to [])? The problem is that the type
of [] is polymorphic: [] :: [a] for all a. Not knowing a Hugs refuses
to print a value of type [a]. Note that this behaviour applies to all
polymorphic values. Given the definition
data Tree a = Empty | Node (Tree a) a (Tree a)
we have, on evaluating
Empty
the error message
ERROR: Cannot find "show" function for:
* expression : Empty
* of type : Tree a
Functions can be shown, but not very helpfully; printing any function
results in
<< function>>
As far as I understand Hugs doesn't know a so it refuses to print it (even though I'm printing a Bool?) so I've tried to make a be an instance of Show, but it still doesn't work, what's the problem here?
Look at the type of debugFunction.
debugFunction :: Show a => a -> Tree a -> Bool
debugFunction expects two arguments, the second of which is a Tree a. You're only passing it one. The type checker sees that you're passing a Tree Int as the first argument and infers a ~ Tree Int. So debugFunction getDebugTree is a function waiting for a second argument of type Tree (Tree Int).
debugFunction getDebugTree :: Tree (Tree Int) -> Bool
I suspect you intended to use getDebugTree as the second argument to debugFunction, which means you need to come up with an Int to use as the first one.
debugFunction 0 getDebugTree :: Bool
The error message about the missing Show instance comes from the REPL itself. It's attempting to print out the result of debugFunction getDebugTree, but it can't because functions can't be shown.

How can I build a recursive tree with concrete data types in 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.

Haskell Type Variable

Learn You a Haskell creates a Tree Algebraic Data Type:
data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)
My understanding is that a can be any type.
So I tried to create a treeInsert function that puts a Tree on the left or right side depending upon its Side value:
data Side = L | R
singletonTree :: a -> Tree a
singletonTree x = Node x EmptyTree EmptyTree
treeInsert :: a -> Tree a -> Tree a
treeInsert x EmptyTree = singletonTree x
treeInsert x#(L, _) (Node a left right) = Node a (treeInsert x left) right -- ERROR
treeInsert x#(R, _) (Node a left right) = Node a left (treeInsert x right)
But I got a compile-time error:
Couldn't match expected type `a' with actual type `(Side, t0)'
`a' is a rigid type variable bound by
the type signature for treeInsert :: a -> Tree a -> Tree a
at File.hs:10:15
In the pattern: (L, _)
In an equation for `treeInsert':
treeInsert x#(L, _) (Node a left right)
= Node a (treeInsert x left) right
Failed, modules loaded: none.
Perhaps a is still any type, but my pattern matching is invalid?
Just because a can be any type in a Tree a in general, doesn't mean it can be any type in a tree passed to treeInsert. You need to refine it to a type that actually allows the (L, _) and (R, _) pattern matches on it.
In fact, you can delete the type annotation on treeInsert and it will compile, after which you can ask GHCi with :t for the correct type (and then re-add that annotation if you want):
treeInsert :: (Side, t) -> Tree (Side, t) -> Tree (Side, t)
treeInsert :: a -> Tree a -> Tree a
So treeInsert is going to get a value of any type, and a tree containing the same type, and result in a tree of the same type.
Your equations try to match x against the patterns (L, _) and the (R, _). But wait; the type said I could call it with any type I liked. I should be able to call it like treeInsert ["this", "is", "a", "list", "of", "String"] EmptyTree. How can I match something of type [String] against a pattern like (L, _); that only works for types of the form (Side, t0) (for any type t0).
Type variables like a are extremely flexible when you call the function; you can use any value at all of any type you like, and the function will just work.
But you're not calling treeInsert, you're implementing it. For the implementer, type variables like a are extremely restrictive rather than flexible. This is an inevitable trade off1. The caller gets the freedom to pick anything they want; the implementer has to provide code that will work for anything the caller might choose (even types that the caller's program made up long after you finish implementing your function).
So you can't test it against a pattern like (L, _). Or any other meaningful pattern. Nor can you pass it to any "concrete" function, only to other functions which will accept any possible type. So in fact in treeInsert with type a -> Tree a -> Tree a, there's no way to use any property at all of the values you're inserting to decide where they'll go; for any property you might like to use to decide whether to put it in the left or right tree, there's no guarantee that the property will be meaningfully defined.
You'll either need to do your insertion based on something you can examine (like the structure of the tree that's also passed in), or use a type that provides less flexibility to the caller and actually gives you some information about the values you're inserting, such as treeInsert :: (Side, t) -> Tree (Side, t) -> Tree (Side, t), as Ørjan Johansen suggested.
1 And that very restrictiveness is actually where Haskell as a whole gets a lot of its power, since a lot of really useful and generic code relies on what functions with certain types can't do.

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