Send Beginners mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1. Re:  Help with types (Daniel Carrera)
   2. Re:  Help with types (Daniel Carrera)
   3. Re:  Help with types (Jason Dusek)
   4. Re:  Help with types (Thomas Davie)
   5. Re:  Help with types (Daniel Fischer)
   6. Re:  Help with types (Daniel Carrera)
   7.  Type families with kind * -> * (Marco T?lio Gontijo e Silva)
   8. Re:  Type families with kind * -> * (Jason Dusek)
   9. Re:  Type families with kind * -> * (Daniel Fischer)


----------------------------------------------------------------------

Message: 1
Date: Thu, 23 Apr 2009 16:17:44 +0200
From: Daniel Carrera <[email protected]>
Subject: Re: [Haskell-beginners] Help with types
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

aditya siram wrote:
> There is a chapter in Real World Haskell [1] devoted to this exact 
> question on this exact piece of code.
> 
> hth,
> -deech
> 
> [1] http://book.realworldhaskell.org/read/profiling-and-optimization.html

Wow. Indeed, that is the exact same piece of code. Thanks.

Daniel.


------------------------------

Message: 2
Date: Thu, 23 Apr 2009 16:25:25 +0200
From: Daniel Carrera <[email protected]>
Subject: Re: [Haskell-beginners] Help with types
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

Thomas Davie wrote:
>> It looks like (/) is happy with Num but doesn't like Int. This 
>> surprises me. I would have thought that Fractional is a kind of Num 
>> and Int is a kind of Fractional
> 
> Int isn't a Fractional because it can't represent fractional numbers.

Sure, but any integer is trivially also a fraction, so I would think 
that it would be an acceptable input for (/). On the other hand, if it 
is at all possible for a Num to contain something that cannot be 
converted to a fraction, then a Num should not be a valid input for (/).


------------------------------

Message: 3
Date: Thu, 23 Apr 2009 07:33:01 -0700
From: Jason Dusek <[email protected]>
Subject: Re: [Haskell-beginners] Help with types
To: Daniel Carrera <[email protected]>
Cc: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=UTF-8

2009/04/23 Daniel Carrera <[email protected]>:
> ...if it is at all possible for a Num to contain something
> that cannot be converted to a fraction, then a Num should not
> be a valid input for (/).

  And it isn't.

    Prelude> :t (/)
    (/) :: forall a. (Fractional a) => a -> a -> a

--
Jason Dusek


------------------------------

Message: 4
Date: Thu, 23 Apr 2009 16:40:49 +0200
From: Thomas Davie <[email protected]>
Subject: Re: [Haskell-beginners] Help with types
To: Daniel Carrera <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=WINDOWS-1252; format=flowed;
        delsp=yes


On 23 Apr 2009, at 16:25, Daniel Carrera wrote:

> Thomas Davie wrote:
>>> It looks like (/) is happy with Num but doesn't like Int. This  
>>> surprises me. I would have thought that Fractional is a kind of  
>>> Num and Int is a kind of Fractional
>> Int isn't a Fractional because it can't represent fractional numbers.
>
> Sure, but any integer is trivially also a fraction, so I would think  
> that it would be an acceptable input for (/). On the other hand, if  
> it is at all possible for a Num to contain something that cannot be  
> converted to a fraction, then a Num should not be a valid input for  
> (/).

The problem here is that (/) also *outputs* that type – if you can't  
represent a fraction, how do you give the result of 1/4?

Bob

------------------------------

Message: 5
Date: Thu, 23 Apr 2009 16:56:37 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Help with types
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="iso-8859-1"

Am Donnerstag 23 April 2009 15:52:00 schrieb Daniel Carrera:
> Daniel Fischer wrote:
> > Try explicitly converting the length to the appropriate type:
> >
> > average xs = sum xs / fromIntegral (length xs)
>
> Thanks. Could you help me understand what's happening?
>
> 1. length returns Int.
> 2. sum returns Num.
> 3. (/) wants Fractional.
>
> It looks like (/) is happy with Num but doesn't like Int.

Not quite. (/) needs a type which is an instance of Fractional. All instances 
of 
Fractional are also instances of Num, so Fractional is more specific than Num.
If you divide the result of sum using (/), sum is used at the less general type 
(Fractional a => [a] -> a).
Every function can be used at all types which are less general than its most 
general type.
In this case it goes like this:

The type checker sees

average xs = sum xs / fromIntegral (length xs)

so average is a function, having type arg -> result where

xs :: arg
sum xs / fromIntegral (length xs) :: result

Now the right hand side, the expression sum xs / fromIntegral (length xs), is 
typed.

(/) has the type Fractional a => a -> a -> a, so from that we can deduce that

sum xs :: Fractional a => a
fromIntegral (length xs) :: Fractional a => a
result = Fractional a => a

, all for the same a.

sum has the type (Num n => [n] -> n), so for the expression sum xs to be well 
formed, xs 
must have the type (Num  n => [n]), and then 

sum xs :: Num n => n

Now that type has to be unified with the type deduced for this subexpression 
above. Since 
the first says whichever type, as long as it's a member of class Fractional and 
the second 
says whichever type, as long as it's a member of class Num, the unification 
yields 
"whichever type, as long as it's a member of both, class Fractional and class 
Num",  
(Fractional a, Num a) => a.
Since Fractional is a subclass of Num, the second condition is implied by the 
first and 
the type simplifies to Fractional a => a. Since the type of xs' elements is th 
same as the 
type of sum xs, the Fractional constraint has to be added to the type of xs 
too, giving 
xs :: Fractional a => [a]
arg = Fractional a => [a]

fromIntegral has type (Integral a, Num b) => a -> b. Since length xs :: Int and 
Int is a 
member of Integral,

fromIntegral (length xs) :: Num n => n

This has to be unified with the type deduced above, giving

fromIntegral (length xs) :: Fractional a => a

, too. Note that (sum xs) and (fromIntegral (length xs)) have the type 
Fractional a => a 
*as subexpressions of sum xs / fromIntegral (length xs)*, in isolation, both 
would have 
the type Num n => n.

Assembling all that, we find

average :: Fractional a => [a] -> a

> This surprises
> me. I would have thought that Fractional is a kind of Num and Int is a
> kind of Fractional,

No, Int is an instance of Integral, which is sort of the opposite of Fractional.
Fractional means that you can freely divide (excluding division by 0 of 
course), things 
like 3.24 make sense, Integral means that things like mod or gcd make sense.
Though it is possible to make a type an instance of both, Fractional and 
Integral, that 
doesn't really make sense.

> so a function that expects Fractional would be happy
> with an Int but maybe not with a Num. But clearly that's not the way it
> works.
>
> 'fromIntegral' converts Int to Num. So obviously, Num is good and Int is
> bad.

The thing is that the types are implicitly universally quantified, so the type 
of 
fromIntegral is really

forall a b. (Integral a, Num b) => a -> b

and the type of 
fromIntegral something
is 
forall b. Num b => b

> But I don't really get why.

fromIntegral says, whatever Num type you want, I can give it to you. In 
particular, if the 
caller wants a Double, fromIntegral provides a Double. If the caller wants any 
type, as 
long as it's a member of Fractional, fromIntegral provides that.

Int is a fixed type, the caller cannot choose which type shall be returned, 
it's always 
just Int, so the caller can only use operations which are defined on Int. (/) 
is not 
defined on Int, because the result of dividing two Ints is rarely an Int. For 
divisions of 
Integral types, there are div and quot (with mod and rem for the remainders).

>
> > will yield a working (albeit inefficient)
> > average :: Fractional a => [a] -> a
>
> Why is it inefficient? How would you make it efficient?

It's inefficient because the list has to be traversed twice, once for the sum 
and once for 
the length. Also, the whole list is kept in memory between the two traversals, 
which is a 
very bad thing for long lists.
To make it efficient, calculate the sum and the length together, as in

average xs = loop 0 0 xs
    where
        loop sm ln [] = sm / fromIntegral ln
        loop sm ln (y:ys) = loop (sm+y) (ln+1) ys

although that probably needs strictness annotations on sm and ln to be 
efficient 
(otherwise, the running sum and length may not be evaluated but build up large 
thunks 
which are only forced at the end and may cause a stack overflow then).

>
> Thanks for the help.
>
> Cheers,
> Daniel.




------------------------------

Message: 6
Date: Thu, 23 Apr 2009 18:26:02 +0200
From: Daniel Carrera <[email protected]>
Subject: Re: [Haskell-beginners] Help with types
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

Daniel Fischer wrote:
> Not quite. (/) needs a type which is an instance of Fractional. All instances 
> of 
> Fractional are also instances of Num, so Fractional is more specific than Num.
> If you divide the result of sum using (/), sum is used at the less general 
> type 
> (Fractional a => [a] -> a).
> Every function can be used at all types which are less general than its most
> general type.

Aahh....  I see. The "sum" part is making more sense now.

So let's see: "sum" is a (Num a => [a] -> a). Every function can be used 
at all types that are less general than its most general type. 
Fractional is a kind of Num. Therefore, "sum" can be used as (Fractional 
a => [a] -> a) to make it compatible with (/).

Thanks for the detailed explanation. It's a lot clearer now.

>> This surprises
>> me. I would have thought that Fractional is a kind of Num and Int is a
>> kind of Fractional,
> 
> No, Int is an instance of Integral, which is sort of the opposite of 
> Fractional.
> Fractional means that you can freely divide (excluding division by 0 of 
> course), things 
> like 3.24 make sense, Integral means that things like mod or gcd make sense.
> Though it is possible to make a type an instance of both, Fractional and 
> Integral, that 
> doesn't really make sense.

This helps. I think I see the problem:

Suppose that Integral was a kind of Fractional, the way I proposed. What 
happens when someone writes (x / y) `mod` z ?  Trying to apply the same 
reasoning you used above:

(/) :: Fractional a => a -> a -> a
mod :: Integral a => a -> a -> a


Using the logic that you explained above, we would have to force (/) to 
give an Integral result, which in general is wrong. And that is a 
reasonable argument why Integral should not be an instance of Fractional.

Am I right more or less?



>> But I don't really get why.
> 
> fromIntegral says, whatever Num type you want, I can give it to you.

... and 'length' says, "whatever Int type you want, I can give it to 
you", but (/) says "I don't want an Int, I want a Fractional" and that's 
why 'length' alone doesn't get along with (/).

I'm beginning to see the reasoning behind Haskell's behaviour, but I 
think I'll need time to get used to it.

Thanks for the help.

Daniel.


------------------------------

Message: 7
Date: Thu, 23 Apr 2009 14:15:05 -0300
From: Marco T?lio Gontijo e Silva <[email protected]>
Subject: [Haskell-beginners] Type families with kind * -> *
To: [email protected]
Message-ID: <1240506905.5271.60.ca...@zezinho>
Content-Type: text/plain

Hello,

I read the type families example at
http://haskell.org/haskellwiki/GHC/Indexed_types and I wanted to do
something similar to the Collects example, but using a type of kind * ->
*:

> class StateFunctor sf where
>   type SFMonad sf
>   type SFValue sf
>   sfmap :: (SFValue sf -> SFValue sf) -> sf -> SFMonad sf ()

I wrote the instance as:

> instance StateFunctor (ListStore a) where
>   type SFMonad (ListStore a) = IO
>   type SFValue (ListStore a) = a
>   sfmap function listStore
>     = listStoreGetSize listStore >>= listStoreSfmap function listStore

> listStoreSfmap :: (a -> a) -> ListStore a -> Int -> IO ()
> listStoreSfmap _function _listStore 0 = []
> listStoreSfmap function listStore size
>   = listStoreGetValue listStore index
>     >>= listStoreSetValue listStore index . function
>   >> listStoreSfmap function listStore index
>   where
>     index :: Int
>     index = pred size

I'm getting:

DistroCreator/GUI/List.hs:51:47:
    Kind error: `SFMonad' is applied to too many type arguments
    In the type `SFMonad sf ()'
    In the type `sf -> SFMonad sf ()'
    In the type `(SFValue sf -> SFValue sf) -> sf -> SFMonad sf ()'
Failed, modules loaded: none.

How can I use type families with types * -> *?

Greetings.

-- 
marcot
http://marcot.iaaeee.org/




------------------------------

Message: 8
Date: Thu, 23 Apr 2009 10:27:00 -0700
From: Jason Dusek <[email protected]>
Subject: Re: [Haskell-beginners] Type families with kind * -> *
To: Marco T?lio Gontijo e Silva <[email protected]>
Cc: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=UTF-8

class StateFunctor sf where
  type SFMonad sf :: * -> *
  type SFValue sf
  sfmap :: (SFValue sf -> SFValue sf) -> sf -> SFMonad sf ()


------------------------------

Message: 9
Date: Thu, 23 Apr 2009 19:32:15 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Type families with kind * -> *
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="iso-8859-15"

Am Donnerstag 23 April 2009 19:15:05 schrieb Marco Túlio Gontijo e Silva:
> Hello,
>
> I read the type families example at
> http://haskell.org/haskellwiki/GHC/Indexed_types and I wanted to do
> something similar to the Collects example, but using a type of kind * ->
>
> *:
> > class StateFunctor sf where
> >   type SFMonad sf
> >   type SFValue sf
> >   sfmap :: (SFValue sf -> SFValue sf) -> sf -> SFMonad sf ()
>
> I wrote the instance as:
> > instance StateFunctor (ListStore a) where
> >   type SFMonad (ListStore a) = IO
> >   type SFValue (ListStore a) = a
> >   sfmap function listStore
> >     = listStoreGetSize listStore >>= listStoreSfmap function listStore
> >
> > listStoreSfmap :: (a -> a) -> ListStore a -> Int -> IO ()
> > listStoreSfmap _function _listStore 0 = []
> > listStoreSfmap function listStore size
> >   = listStoreGetValue listStore index
> >
> >     >>= listStoreSetValue listStore index . function
> >   >>
> >   >> listStoreSfmap function listStore index
> >
> >   where
> >     index :: Int
> >     index = pred size
>
> I'm getting:
>
> DistroCreator/GUI/List.hs:51:47:
>     Kind error: `SFMonad' is applied to too many type arguments
>     In the type `SFMonad sf ()'
>     In the type `sf -> SFMonad sf ()'
>     In the type `(SFValue sf -> SFValue sf) -> sf -> SFMonad sf ()'
> Failed, modules loaded: none.
>
> How can I use type families with types * -> *?

For example:
-----------------------------------
{-# LANGUAGE TypeFamilies, KindSignatures #-}
module TypeF where

data ListStore a = Dummy

listStoreGetSize = undefined
listStoreSfmap = undefined

class StateFunctor sf where
   type SFMonad sf :: (* -> *)
   type SFValue sf
   sfmap :: (SFValue sf -> SFValue sf) -> sf -> SFMonad sf ()

instance StateFunctor (ListStore a) where
   type SFMonad (ListStore a) = IO
   type SFValue (ListStore a) = a
   sfmap function listStore
     = listStoreGetSize listStore >>= listStoreSfmap function listStore

-------------------------------------
Prelude> :l TypeF
[1 of 1] Compiling TypeF            ( TypeF.hs, interpreted )
Ok, modules loaded: TypeF.


>
> Greetings.



------------------------------

_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners


End of Beginners Digest, Vol 10, Issue 25
*****************************************

Reply via email to