Don't understand this collection class syntax - haskell

class Collection c where
empty :: c key value
singleton :: key -> value -> c key value
insert
:: Ord key
=> key -> value -> c key value -> c key value
lookup :: Ord key => key -> c key value -> Maybe value
delete :: Ord key => key -> c key value -> c key value
keys :: c key value -> [key]
values :: c key value -> [value]
toList :: c key value -> [(key, value)]
fromList :: Ord key => [(key,value)] -> c key value
This is unlike what I've read about typeclasses, or the syntax I'm used to. I don't understand what c key value represents. Also, what is empty supposed to be? It doesn't resemble a function. Appreciate and am thankful for any help, I'm new to haskell and this is confusing for me

The type parameter c will here not unify with a "concrete" type, but with a type constructor that still expects two parameters.
A simple collection could be:
data ListMap a b = ListMap [(a, b)]
then we define an instance of Collection with:
instance Collection ListMap where
empty = ListMap []
-- …
Indeed, empty here has as type c key value, so ListMap key value, which is then a concrete type.
In this case, a function like fromList :: Ord key => [(key,value)] -> c key value will thus result in fromList :: Ord key => [(key,value)] -> ListMap key value.

You can infer from how key and value are used that they must be types (things of kind *). Thus, from how c is used, you can infer that it must be something of kind * -> * -> *: it gets applied to two types to produce another type.
With the KindSignatures extension, we can make this more explicit. You could write
{-# LANGUAGE KindSignatures #-}
class Collection (c :: * -> * -> *) where
empty :: c key value
-- etc.

Related

Unpacking tuples using "Either" in Haskell

I'm trying to get a grip on how tuples work in Haskell.
I came across this type constructor leftRight :: (Either a b -> c) -> (a -> c, b -> c) and I'm struggling to see what it does.
So we have (Either a b -> c)which means that either a is applied to c or b is applied to c. But the output is a tuple?
Does that mean that it splits the function so that left side of the tuple takes in argument given at a and right side takes argument given at right?
How would this look in code?
"I came across this type constructor..."
It's not a type constructor - it's a function type declaration.
The -> separates out the parameter types. The final one is the return type, and the previous ones are the input types.
Hence leftRight :: (Either a b -> c) -> (a -> c, b -> c) takes one input and returns one output.
Input function: (Either a b -> c)
Output function pair: (a -> c, b -> c)
The parentheses contain the functions.
The first function takes an Either type (left value is the error type, a, and the right value is the OK type, 'b' - it helps me to think of the latin, sinister for left, and dexter for right - your mileage may vary) as the input and returns something of type c.
The second function comes as a tuple of two separate functions, one is a -> c, and one is b -> c.
A concrete version: type a is a String to contain my error message, type bis an Int, and type c is another string.
leftRight :: (Either String Int -> String) -> (String -> String, Int -> String)
So we have Either a b -> c which means that either a is applied to c or b is applied to c
Wrong, or at least badly worded. Nothing is “applied to c” here.
What it actually means is: the function can accept an a-value or a b-value, and in either case produces a c-value.
This is equivalent to having both a function that accepts only a-values and gives c-results, and one that accepts only b-values and gives c-results. The tuple groups both of these functions together.
It might help to look at an example to illustrate:
fryPancake :: Either Butter Margarine -> Pancake
[Assume we've already taken care of the flour, eggs etc. in the batter]
From this you can obtain both
fryPancakeWithButter :: Butter -> Pancake
fryPancakeWithButter b = fryPancake (Left b)
fryPancakeWithMargarine :: Margarine -> Pancake
fryPancakeWithMargarine m = fryPancake (Right m)
Now you just group both of these together:
fryPancake' :: (Butter -> Pancake, Margarine -> Pancake)
fryPancake' = (fryPancakeWithButter, fryPancakeWithMargarine)
...which is the same as
fryPancake' = leftRight fryPancake
The input to leftRight is a function and the output is two functions. The tuple is barely relevant, except that it groups the two functions together into a single output, so leftRight can return both of them at once.
One function's type is a -> c and the other one's type is b -> c. Presumably, the first function wraps the a in Left and then calls the original function, and the second one wraps the b in Right and then calls the original function:
leftRight :: (Either a b -> c) -> (a -> c, b -> c)
leftRight original = (leftFunc, rightFunc)
where
leftFunc aVal = original (Left aVal)
rightFunc bVal = original (Right bVal)
The key is to use function composition. A function of type a -> c can be created from functions of type a -> Either a b and Either a b -> c. You have Left :: a -> Either a b and you have the argument f :: Either a b -> c passed to leftRight.
The same argument lets you construct a function of type b -> c similarly. This gives you
leftRight :: (Either a b -> c) -> (a -> c, b -> c)
leftRight f = let g1 = ...
g2 = ...
in (g1, g2)
I leave the definitions of g1 and g2 as an exercise.

Union type (a -> b | IO b) in Haskell?

I need to define a Union Type which the set of the type includes
a -> b OR a -> IO b
a -> b || a -> IO b
or
a -> b | IO b
foo :: (a -> b | IO b) -> IO (R a) -> IO (R b)
I tried data unionType b = b | IO b that does not work.
Not a data constructor: ‘b’parser
No quick fixes available
Is it possible in Haskell?
In Haskell, a sum type (the standard term for a disjoint union type) requires explicit "constructors" for its components, so you need to write something like:
data BarType b = BarPure b | BarIO (IO b)
This defines a type BarType, and it also defines constructors BarPure and BarIO for use in constructing values of this type:
val1, val2 :: BarType String
val1 = BarPure "pure"
val2 = BarIO getLine
and consuming values of this type via case-matching:
runBar :: BarType b -> IO b
runBar barb = case barb of
BarPure s -> pure s
BarIO act -> act
There are two issues: On the one hand your type must be upper-case, that is UnionType. Second, you need to define type constructors to be able to create a value of said data type. So the closest would be e.g.
data UnionType b = Left b | Right (IO b)
Here I chose the arbitrary names Left and Right for the constructors, but you can use any you like.
If the Left/Right constructors seem familiar to you, that is because Either uses these by default, and can do exactly the same with a slightly "cheaper" type synonym:
type UnionType b = Either b (IO b)
Of course in both cases we have to deconstruct the type to get to the actual values of b and IO b.
EDIT: As #leftroundabout mentioned, it is not very convenient to define a data type with type constructors called Left and Right, as these constructors are already used with the built in Either.

Creating data types containing lists and defining functions on them

Informally speaking, I made a data type Tdict where each instance of it is a list of pairs, and each pair consists of a String and a List of Strings; in other languages, I would use a Hash, mapping Strings to Lists of Strings. Since I am learning Haskell, I would like to roll out this structure from scratch, instead of using the Hash package from Haskell.
This is my data type definition of Tdict, using two auxiliary type definitions:
-- Pair of two strings
data TPair = TPair String String deriving (Show)
-- Associating one String to a list of Strings
data Tassoc = Tassoc String [String] deriving (Show)
-- type synonym for list of associations
type Tdict = [Tassoc]
So far, this is accepted by Haskell, so at least it is syntactically correct. Now I want to define a function, which takes as parameter two strings and a Tdict and returns a Tdict. However, Haskell already rejects the signature definition of the function:
insertTdict :: (String k, String v, Tdict d) => k -> v -> d -> Tdict
The error message is about both parameters v and `d and reads:
error:
• Expected kind ‘* -> Constraint’, but ‘Tdict’ has kind ‘*’
• In the type signature:
insertTdict :: (String k, String v, Tdict d) =>
k -> v -> d -> Tdict
(The error messages for parameters v and d are identical).
What did I do wrong? I have the feeling, that I am missing something fundamental in Haskell.
I used this page as a reference for defining my data types.
Your types are not typeclasses. A type constraint like (String k, String v, Tdict d) => thus does not make sense.
You can implement the function with:
insertTdict :: String -> String -> Tdict -> Tdict

MultiParamTypeClasses - Why is this type variable ambiguous?

Suppose I define a multi-parameter type class:
{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes, FlexibleContexts, FlexibleInstances #-}
class Table a b c where
decrement :: a -> a
evalutate :: a -> b -> c
Then I define a function that uses decrement, for simplicity:
d = decrement
When I try to load this in ghci (version 8.6.3):
• Could not deduce (Table a b0 c0)
arising from a use of ‘decrement’
from the context: Table a b c
bound by the type signature for:
d :: forall a b c. Table a b c => a -> a
at Thing.hs:13:1-28
The type variables ‘b0’, ‘c0’ are ambiguous
Relevant bindings include d :: a -> a (bound at Thing.hs:14:1)
These potential instance exist:
instance Table (DummyTable a b) a b
This is confusing to me because the type of d is exactly the type of decrement, which is denoted in the class declaration.
I thought of the following workaround:
data Table a b = Table (a -> b) ((Table a b) -> (Table a b))
But this seems notationally inconvenient, and I also just wanted to know why I was getting this error message in the first place.
The problem is that, since decrement only requires the a type, there is no way to figure out which types b and c should be, even at the point where the function is called (thus solving the polymorphism into a specific type) - therefore, GHC would be unable to decide which instance to use.
For example: let's suppose you have two instances of Table: Table Int String Bool, and Table Int Bool Float; you call your function d in a context where it is supposed to map an Int to another Int - problem is, that matches both instances! (a is Int for both).
Notice how, if you make your function equal to evalutate:
d = evalutate
then the compiler accepts it. This is because, since evalutate depends on the three type parameters a, b, and c, the context at the call site would allow for non-ambiguous instance resolution - just check which are the types for a, b, and c at the place where it is called.
This is, of course, not usually a problem for single-parameter type classes - only one type to resolve; it is when we deal with multiple parameters that things get complicated...
One common solution is to use functional dependencies - make b and c depend on a:
class Table a b c | a -> b c where
decrement :: a -> a
evalutate :: a -> b -> c
This tells the compiler that, for every instance of Table for a given type a, there will be one, and only one, instance (b and c will be uniquely determined by a); so it will know that there won't be any ambiguities and accept your d = decrement happily.

Basic Haskell function types?

Super basic question - but I can't seem to get a clear answer. The below function won't compile:
randomfunc :: a -> a -> b
randomfunc e1 e2
| e1 > 2 && e2 > 2 = "Both greater"
| otherwise = "Not both greater"
main = do
let x = randomfunc 2 1
putStrLn $ show x
I'm confused as to why this won't work. Both parameters are type 'a' (Ints) and the return parameter is type 'b' (String)?
Error:
"Couldn't match expected type ‘b’ with actual type ‘[Char]’"
Not quite. Your function signature indicates: for all types a and b, randomfunc will return something of type b if given two things of type a.
However, randomFunc returns a String ([Char]). And since you compare e1 with 2 each other, you cannot use all a's, only those that can be used with >:
(>) :: Ord a => a -> a -> Bool
Note that e1 > 2 also needs a way to create such an an a from 2:
(> 2) :: (Num a, Ord a) => a -> Bool
So either use a specific type, or make sure that you handle all those constraints correctly:
randomfunc :: Int -> Int -> String
randomFunc :: (Ord a, Num a) => a -> a -> String
Both parameters are type 'a' (Ints) and the return parameter is type 'b' (String)?
In a Haskell type signature, when you write names that begin with a lowercase letter such as a, the compiler implicitly adds forall a. to the beginning of the type. So, this is what the compiler actually sees:
randomfunc :: forall a b. a -> a -> b
The type signature claims that your function will work for whatever ("for all") types a and b the caller throws at you. But this is not true for your function, since it only works on Int and String respectively.
You need to make your type more specific:
randomfunc :: Int -> Int -> String
On the other hand, perhaps you intended to ask the compiler to fill out a and b for you automatically, rather than to claim that it will work for all a and b. In that case, what you are really looking for is the PartialTypeSignatures feature:
{-# LANGUAGE PartialTypeSignatures #-}
randomfunc :: _a -> _a -> _b

Resources