Fundeps: I feel dumb

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Fundeps: I feel dumb

Creighton Hogg-4
Hi,
So I'm trying the fun-deps example from
http://www.haskell.org/hawiki/FunDeps and seeing if I can
use it, but I can't really get things to work the way I want.
The code follows below, and the error I get if I try to multiply
10 <*> (vector 10 [0..9]) is

    No instance for (MatrixProduct a (Vec b) c)
      arising from use of `<*>' at <interactive>:1:3-5
    Probable fix: add an instance declaration for (MatrixProduct a (Vec b) c)
    In the definition of `it': it = 10 <*> (vector 10 ([0 .. 9]))



import Array
-- The elements and the size
data Vec a = Vec (Array Int a) Int
           deriving (Show,Eq)
type Matrix a = (Vec (Vec a))
class MatrixProduct a b c | a b -> c where
    (<*>) :: a -> b -> c
instance (Num a) => MatrixProduct a (Vec a) (Vec a) where
    (<*>) num (Vec a s) = Vec (fmap (*num) a) s
vector n elms = Vec (array (0,n-1) $ zip [0..n-1] elms) n
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Fundeps: I feel dumb

oleg-7

Creighton Hogg wrote:

>     No instance for (MatrixProduct a (Vec b) c)
>       arising from use of `<*>' at <interactive>:1:3-5
>     Probable fix: add an instance declaration for (MatrixProduct a
>     (Vec b) c)
>     In the definition of `it': it = 10 <*> (vector 10 ([0 .. 9]))

Let us look at the instance

  class MatrixProduct a b c | a b -> c where
    (<*>) :: a -> b -> c
  instance (Num a) => MatrixProduct a (Vec a) (Vec a) where

it defines what happens when multiplying a vector of some numeric type
'a' by a value _of the same_ type. Let us now look at the error
message:
> (MatrixProduct a (Vec b) c)

That is, when trying to compile your expression
        10 <*> (vector 10 ([0 .. 9]))
the typechecker went looking for (MatrixProduct a (Vec b) c)
where the value and the vector have different numeric types. There is
no instance for such a general case, hence the error. It is important
to remember that the typechecker first infers the most general type
for an expression, and then tries to resolve the constraints. In your
expression,
        10 <*> (vector 10 ([0 .. 9]))
we see constants 10, 10, 0, 9. Each constant has the type Num a => a.
Within the expression 0 .. 9, both 0 and 9 must be of the same type
(because [n .. m] is an abbreviation for enumFromThen n m, and
according
to the type of the latter
          enumFromThen :: a -> a -> [a]
both arguments must be of the same type).

But there is nothing that says that the first occurrence of 10 must be
of the same numeric type as the occurrence of 9. So, the most general
type assignment will be (Num a => a) for 10, and (Num b => b) for 9.

Solution: either choose a specific (non-polymorphic type)

> test1 = (10::Int) <*> (vector 10 [0..9::Int])

Or tell the typechecker that those constants must be of the same type:

> test2 = let n = 10 in n <*> (vector 10 [0..(9 `asTypeOf` n)])
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Fundeps: I feel dumb

Creighton Hogg-4
On 13 Apr 2006 03:27:03 -0000, [hidden email] <[hidden email]> wrote:

>
> Creighton Hogg wrote:
>
> >     No instance for (MatrixProduct a (Vec b) c)
> >       arising from use of `<*>' at <interactive>:1:3-5
> >     Probable fix: add an instance declaration for (MatrixProduct a
> >     (Vec b) c)
> >     In the definition of `it': it = 10 <*> (vector 10 ([0 .. 9]))
>
> Let us look at the instance
>
>   class MatrixProduct a b c | a b -> c where
>     (<*>) :: a -> b -> c
>   instance (Num a) => MatrixProduct a (Vec a) (Vec a) where
>
> it defines what happens when multiplying a vector of some numeric type
> 'a' by a value _of the same_ type. Let us now look at the error
> message:
> >       (MatrixProduct a (Vec b) c)
>
> That is, when trying to compile your expression
>         10 <*> (vector 10 ([0 .. 9]))
> the typechecker went looking for (MatrixProduct a (Vec b) c)
> where the value and the vector have different numeric types. There is
> no instance for such a general case, hence the error. It is important
> to remember that the typechecker first infers the most general type
> for an expression, and then tries to resolve the constraints. In your
> expression,
>         10 <*> (vector 10 ([0 .. 9]))
> we see constants 10, 10, 0, 9. Each constant has the type Num a => a.
> Within the expression 0 .. 9, both 0 and 9 must be of the same type
> (because [n .. m] is an abbreviation for enumFromThen n m, and
> according
> to the type of the latter
>           enumFromThen :: a -> a -> [a]
> both arguments must be of the same type).
>
> But there is nothing that says that the first occurrence of 10 must be
> of the same numeric type as the occurrence of 9. So, the most general
> type assignment will be (Num a => a) for 10, and (Num b => b) for 9.

Thank you very much for the explanation:  it makes alot of sense.
So, if one does not want to for alot of type declarations into the
code, which would be fairly awkward, is there a way to do this with
fundeps or other type extensions that will be alot prettier or is any
way of defining type classes going to run into the same problems?
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe