Couldn't match type `h' with `String' - haskell

I'm starting in Haskell and I would like your help and intuition on why the following code does not work. The main idea is to do a class that represents Probability mass functions
--a encapsulates a set of hypotheses of type h
class Pmf a where
hypos :: a -> [h]
prob :: a -> h -> Double
probList :: a -> [(h,Double)]
probList a = map (\h->(h, prob a h)) $ hypos a
The idea is for it to be general, so for instance I could define
data BoxSet = BoxSet { ids::[String], items::[(String,Int)]} deriving(Show)
and make BoxSet an instance like
instance Pmf BoxSet where
hypos = ids
prob cj _ = let one = 1
len = doubleLength $ ids cj in one/len
but this gives the following error
<interactive>:2:13: error:
* Couldn't match type `h' with `String'
`h' is a rigid type variable bound by
the type signature for:
hypos :: forall h. BoxSet -> [h]
at <interactive>:2:5
Expected type: BoxSet -> [h]
Actual type: BoxSet -> [String]
* In the expression: ids
In an equation for `hypos': hypos = ids
In the instance declaration for `Pmf BoxSet'
* Relevant bindings include hypos :: BoxSet -> [h] (bound at <interactive>:2:5)
Its possible to put h as additional class parameter but then in the future I will expand the class with a new type d for data and i will have this problem
So then, I would appreciate if you could tell me why String can not be matched as h and how could this be solved. I understand that it expects any h with any type but in an instance it makes sense to give h a specific type.
Also, I think I might not be on the functional mindset fully here. So if you can point a better way to model these Pmf I would gladly try it!.

This
class Pmf a where
hypos :: a -> [h]
prob :: a -> h -> Double
is short for
class Pmf a where
hypos :: forall h. a -> [h]
prob :: forall h. a -> h -> Double
That is, the hs in the two signatures are unrelated, and furthermore each of these functions needs to work for any h that the caller might choose. I think you are looking for either type families
class Pmf a where
type Hypothesis a :: *
hypos :: a -> [Hypothesis a]
...
instance Pmf BoxSet where
type Hypothesis BoxSet = String
...
or functional dependencies, which do the same kind of thing but with a different swagger
class Pmf a h | a -> h where
hypos :: a -> [h]
...
instance Pmf BoxSet String where
...
There are a handful of extensions needed for each, I think the error messages will lead the way.

Related

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.

Why does Haskell's Monad implementation fail function result differ from error's result?

I am trying to understand monads and reading it's type class definition:
class Monad m where
.
.
.
fail :: String -> m a
fail msg = error msg
Now, the definition of error is:
error :: [Char] -> a
Shouldn't the type system complain in this case? as
a /= m a
Or does the type system automatically assume that the results from error will be transformed into
m a
somehow?
Thanks in advance
The as in fail's and error's type signatures are a type variables. We can rename them without changing their meaning, e.g.
error :: [Char] -> b
error :: [Char] -> c
error :: [Char] -> d
All those type signatures have the same meaning; we just used alpha conversion on the type level.
Now we set b ~ m a, where m is fixed by fail's context and we see that error can get used:
fail :: String -> m a
fail msg = error msg -- error :: String -> b
-- b ~ m a

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

How do you apply function constraints in instance methods in Haskell?

I'm learning how to use typeclasses in Haskell.
Consider the following implementation of a typeclass T with a type constrained class function f.
class T t where
f :: (Eq u) => t -> u
data T_Impl = T_Impl_Bool Bool | T_Impl_Int Int | T_Impl_Float Float
instance T T_Impl where
f (T_Impl_Bool x) = x
f (T_Impl_Int x) = x
f (T_Impl_Float x) = x
When I load this into GHCI 7.10.2, I get the following error:
Couldn't match expected type ‘u’ with actual type ‘Float’
‘u’ is a rigid type variable bound by
the type signature for f :: Eq u => T_Impl -> u
at generics.hs:6:5
Relevant bindings include
f :: T_Impl -> u (bound at generics.hs:6:5)
In the expression: x
In an equation for ‘f’: f (T_Impl_Float x) = x
What am I doing/understanding wrong? It seems reasonable to me that one would want to specialize a typeclass in an instance by providing an accompaning data constructor and function implementation. The part
Couldn't match expected type 'u' with actual type 'Float'
is especially confusing. Why does u not match Float if u only has the constraint that it must qualify as an Eq type (Floats do that afaik)?
The signature
f :: (Eq u) => t -> u
means that the caller can pick t and u as wanted, with the only burden of ensuring that u is of class Eq (and t of class T -- in class methods there's an implicit T t constraint).
It does not mean that the implementation can choose any u.
So, the caller can use f in any of these ways: (with t in class T)
f :: t -> Bool
f :: t -> Char
f :: t -> Int
...
The compiler is complaining that your implementation is not general enough to cover all these cases.
Couldn't match expected type ‘u’ with actual type ‘Float’
means "You gave me a Float, but you must provide a value of the general type u (where u will be chosen by the caller)"
Chi has already pointed out why your code doesn't compile. But it's not even that typeclasses are the problem; indeed, your example has only one instance, so it might just as well be a normal function rather than a class.
Fundamentally, the problem is that you're trying to do something like
foobar :: Show x => Either Int Bool -> x
foobar (Left x) = x
foobar (Right x) = x
This won't work. It tries to make foobar return a different type depending on the value you feed it at run-time. But in Haskell, all types must be 100% determined at compile-time. So this cannot work.
There are several things you can do, however.
First of all, you can do this:
foo :: Either Int Bool -> String
foo (Left x) = show x
foo (Right x) = show x
In other words, rather than return something showable, actually show it. That means the result type is always String. It means that which version of show gets called will vary at run-time, but that's fine. Code paths can vary at run-time, it's types which cannot.
Another thing you can do is this:
toInt :: Either Int Bool -> Maybe Int
toInt (Left x) = Just x
toInt (Right x) = Nothing
toBool :: Either Int Bool -> Maybe Bool
toBool (Left x) = Nothing
toBool (Right x) = Just x
Again, that works perfectly fine.
There are other things you can do; without knowing why you want this, it's difficult to suggest others.
As a side note, you want to stop thinking about this like it's object oriented programming. It isn't. It requires a new way of thinking. In particular, don't reach for a typeclass unless you really need one. (I realise this particular example may just be a learning exercise to learn about typeclasses of course...)
It's possible to do this:
class Eq u => T t u | t -> u where
f :: t -> u
You need FlexibleContextx+FunctionalDepencencies and MultiParamTypeClasses+FlexibleInstances on call-site. Or to eliminate class and to use data types instead like Gabriel shows here

Type class definition with functions depending on an additional type

Still new to Haskell, I have hit a wall with the following:
I am trying to define some type classes to generalize a bunch of functions that use gaussian elimination to solve linear systems of equations.
Given a linear system
M x = k
the type a of the elements m(i,j) \elem M can be different from the type b of x and k. To be able to solve the system, a should be an instance of Num and b should have multiplication/addition operators with b, like in the following:
class MixedRing b where
(.+.) :: b -> b -> b
(.*.) :: (Num a) => b -> a -> b
(./.) :: (Num a) => b -> a -> b
Now, even in the most trivial implementation of these operators, I'll get Could not deduce a ~ Int. a is a rigid type variable errors (Let's forget about ./. which requires Fractional)
data Wrap = W { get :: Int }
instance MixedRing Wrap where
(.+.) w1 w2 = W $ (get w1) + (get w2)
(.*.) w s = W $ ((get w) * s)
I have read several tutorials on type classes but I can find no pointer to what actually goes wrong.
Let us have a look at the type of the implementation that you would have to provide for (.*.) to make Wrap an instance of MixedRing. Substituting Wrap for b in the type of the method yields
(.*.) :: Num a => Wrap -> a -> Wrap
As Wrap is isomorphic to Int and to not have to think about wrapping and unwrapping with Wrap and get, let us reduce our goal to finding an implementation of
(.*.) :: Num a => Int -> a -> Int
(You see that this doesn't make the challenge any easier or harder, don't you?)
Now, observe that such an implementation will need to be able to operate on all types a that happen to be in the type class Num. (This is what a type variable in such a type denotes: universal quantification.) Note: this is not the same (actually, it's the opposite) of saying that your implementation can itself choose what a to operate on); yet that is what you seem to suggest in your question: that your implementation should be allowed to pick Int as a choice for a.
Now, as you want to implement this particular (.*.) in terms of the (*) for values of type Int, we need something of the form
n .*. s = n * f s
with
f :: Num a => a -> Int
I cannot think of a function that converts from an arbitary Num-type a to Int in a meaningful way. I'd therefore say that there is no meaningful way to make Int (and, hence, Wrap) an instance of MixedRing; that is, not such that the instance behaves as you would probably expect it to do.
How about something like:
class (Num a) => MixedRing a b where
(.+.) :: b -> b -> b
(.*.) :: b -> a -> b
(./.) :: b -> a -> b
You'll need the MultiParamTypeClasses extension.
By the way, it seems to me that the mathematical structure you're trying to model is really module, not a ring. With the type variables given above, one says that b is an a-module.
Your implementation is not polymorphic enough.
The rule is, if you write a in the class definition, you can't use a concrete type in the instance. Because the instance must conform to the class and the class promised to accept any a that is Num.
To put it differently: Exactly the class variable is it that must be instantiated with a concrete type in an instance definition.
Have you tried:
data Wrap a = W { get :: a }
Note that once Wrap a is an instance, you can still use it with functions that accept only Wrap Int.

Resources