Trying to search for an element in a listed tuple that has a new datatype - haskell

I've created a new datatype Board:
data Board a = Grid [(Position, Maybe a)]
deriving (Eq, Show)
where Position is its own datatype:
data Position = NW | N | NE | W | M | E | SW | S | SE
deriving (Eq, Ord, Show)
Now I'm trying to create a function label, that takes a Position and Board and returns the label at the given position (wrapped using Just) or Nothing if the given position is empty.
I was thinking of implementing a new function Search to do this.
search :: (Eq a) => a -> [(a,b)] -> Maybe b
search _ [] = Nothing
search x ((a,b):xs) = if x == a then Just b else search x xs
But I don't know how to pass in the List [(a,b)] from my Board input. I tried:
label :: Position -> Board a -> Maybe a
label p b = Search p b
and got the error:
* Couldn't match expected type: [(Position, a)]
with actual type: Board a
* In the second argument of `lookup', namely `b'
In the expression: lookup p b
In an equation for `label': label p b = lookup p b
* Relevant bindings include
b :: Board a (bound at A6.hs:21:9)
label :: Position -> Board a -> Maybe a (bound at A6.hs:21:1)
Perhaps there's an easier way to go about this, but this is the only way I could think of.
(Aplet123 pointed out a mistake, since updated and updated the error produced)

You need to look into your data type under the wraps to find the actual datum there,
label :: Position -> Board a -> Maybe a
label p (Grid b) = search p b
-- ^^^^
Function names in Haskell must not be capitalized. That is reserved for types and data constructors.
The above will give you another type error but you'll be able to tweak it, I believe, to get it fixed. For starters, enter the definition without the type signature, to see what type is inferred for 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.

The Type signature lacks an appropriate binding [Haskell]

I have been googling around to find the answer, and even came to a few questions asked here. It seems that this is an ambiguous error and I can't figure out how to solve it in my instance.
The offending code is below:
pos :: (Eq a) => [a] -> a -> Int
pos [] _ = -1
pos (x:xs) y
| not $ elem y (x:xs) = -1
| x == y = 0
| otherwise = 1 + pos xs y
-- Get the same element from another range as one element of the first range.
refPos :: (Eq a) => [a] -> [b] -> a -> b
refPos r1 r2 e1 = r2 !! (r1 `pos` e1)
letterNumber :: (Eq a, Char a) => a -> Int
lettNumber x = refPos ['a'..'z'] [0..25] x
The text of the exact error is:
15:1 The type signature for letterNumber lacks an accompanying binding.
Originally the type signature I put was Char -> Int, but that didn't work (it said something about Eq, but I'm too new too Haskell to interpret it properly). So I changed the type signature to have an Eq class constraint. If someone can point out what is wrong or a workaround, it would be greatly appreciated as this is a doorstop problem to a project I'm working on.
You provide a type signature for letterNumber, but then provide a binding for lettNumber. Note the missing er.
Just rename lettNumber to letterNumber, to match the spelling in the type signature.
Also, the correct type signature for letterNumber is
letterNumber :: Char -> Int

Data initialization and data members change in Haskell

I'm new to Haskell and I cannot figure out how you declare a "Data" type and how you can initialize a variable with that type. I'd also like to know how can I change the values of certain members of that variable. For exaple :
data Memory a = A
{ cameFrom :: Maybe Direction
, lastVal :: val
, visited :: [Direction]
}
Direction is a Data type that contains N,S,E,W
val is a Type int
init :: Int -> a
init n = ((Nothing) n []) gives me the following error:
The function `Nothing' is applied to two arguments,
but its type `Maybe a0' has none
In the expression: ((Nothing) n [])
In an equation for `init': init n = ((Nothing) n [])
how can I fix this ?
UPDATE: That did it, thank you very much, but now i have another issue
move :: val -> [Direction] -> Memory -> Direction
move s cs m | s < m.lastVal = m.cameFrom
| ...
this gives me the following error:
Couldn't match expected type `Int' with actual type `a0 -> c0'
Expected type: val
Actual type: a0 -> c0
In the second argument of `(<)', namely `m . lastVal'
In the expression: s < m . lastVal
UPDATE 2: Again, that helped me a lot, thank you very much
Also, I have another question (sorry for being such a bother)
How do I adress only an element of a type
For example if I have
Type Cell = (Int, Int)
Type Direction = (Cell, Int)
how do I proceed if I want to compare a Cell variable with the Cell element of a Direction variable?
As to the update. The syntax
m.lastVal
and
m.cameFrom
is not what you want. Instead
move s cs m | s < lastVal m = cameFrom m
accessors are just functions, so used in prefix form. The . in Haskell is used for namespace resolution (which is not path dependent) and for function composition
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f (g x)
To initialise:
init :: Int -> Memory Int
init n = A {cameFrom = Nothing, lastVal = n, visited = []}
To change values: strictly speaking you don't change values, you return another different value, like this:
toGetBackTo :: Direction -> Memory a -> Memory a
toGetBackTo dir memory = memory {cameFrom = Just dir, visited = dir : visited memory}

Haskell data structures oddity

I've been attempting to write a small file to try out a bag-like data structure. So far my code is as follows:
data Fruit = Apple | Banana | Pear deriving (Eq, Show)
data Bag a = EmptyBag | Contents [(a, Integer)]
emptyBag :: Bag a
emptyBag = EmptyBag
unwrap :: [a] -> a
unwrap [x] = x
isObject theObject (obj, inte) = theObject == obj
count :: Bag a -> a -> Integer
count (Contents [xs]) theObject = snd (unwrap (filter (isObject theObject) [xs]))
count EmptyBag _ = 0
But when I try and run it I get the error
Could not deduce (Eq a) from the context ()
arising from a use of 'isObject' at ....
Whereas when I take the count function out and call
snd(unwrap(filter (isObject Banana) [(Apple,1),(Banana,2)]))
it happily returns 2.
Any clues on why this is, or advice on writing this kind of data structure would be much appreciated.
(==) can only be used in a context that includes Eq, but when you declared count you didn't include that context. If I'm reading correctly, that would be
count :: Eq a => Bag a -> a -> Integer
If you declare count without including the type, you can ask ghci for the inferred type; or just ask for the inferred type of snd (unwrap (filter (isObject Banana) [(Apple,1),(Banana,2)]))

Resources