ElBrocas
ElBrocas

Reputation: 399

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

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

Answers (1)

luqui
luqui

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 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.

Upvotes: 3

Related Questions