Reputation: 399
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!.
Upvotes: 2
Views: 86
Reputation: 60503
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 h
s 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.
Upvotes: 3