I am doing some readings and I found something seems to be interesting.
People sometime will try to represent a quantity-regard-only data structure
(such a order-regadless List) using functions instead of ta concrete data
structure (like the haskell build-in []), any particular reason for this?
For example,
> data Sex = Male | Female
> classA :: Sex -> Int
> classA Male = 100
> classA Female = 200
when I should prefer the above solution instead of using a concrete data structure
such as [] to represent the classA members?
It seems to be very difficult to change the number of Male or Female if a concrete data
structure is not used. Is it possible change the number of Male in classA when represent
classA using function?
Thank you very much!
Best wishes,
Raeck
_________________________________________________________________
It’s the same Hotmail®. If by “same” you mean up to 70% faster.
http://windowslive.com/online/hotmail?ocid=TXT_TAGLM_WL_hotmail_acq_broad1_122008
One important difference between Sex -> Int and [(Sex,Int)] is that
the first guarantees exactly one Int per Sex and has no underlying
order. (That is, [(Male,100),(Female,200)] and
[(Female,200),(Male,100)] are distinct lists but represent the same
map.)
> It seems to be very difficult to change the number of Male or Female if a
> concrete data structure is not used. Is it possible change the number of Male in classA
> when represent classA using function?
Here's the simplest way:
update k v map = \k' -> if k' == k then v else map k'
Note that it requires an Eq instance for Sex.
let classA' = update Male 150 classA
in (classA' Male, classA' Female)
=
(150,200)
--
Dave Menendez <da...@zednenem.com>
<http://www.eyrie.org/~zednenem/>
_______________________________________________
Haskell-Cafe mailing list
Haskel...@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Of course this version of update leaks crazy amounts of memory:
> let bigmap = iterate (update Male 150) classA !! 100000
> bigmap Male
"bigmap" leaves a huge chain of thunks pointing at each other, which
can never be freed.
Using functions is mathematically more elegant than some concrete data
structure (which might require Eq or Ord or other constraints, and
have multiple observable representations for the same map, or have
maps that don't include every element).
However, "generic maps" have been improving a lot recently, especially
with data families in the new GHC. You use an abstract type (k :->
v) to represent the map; this type is semantically equivalent to (k ->
v) via some observation function for generic maps, but has a compact
representation. For example:
> class MapKey k where
> data k :-> v
> newMap :: (k -> v) -> (k :-> v)
> fetch :: (k :-> v) -> (k -> v)
> update :: (k,v) -> (k :-> v) -> (k :-> v)
> empty :: v -> (k :-> v)
> empty = newMap (const v)
> instance MapKey Bool where
> data Bool :-> v = BoolMap v v
> newMap f = BoolMap (f False) (f True)
> fetch (Boolmap t f) v = if v then t else f
> update (True, t) (BoolMap _ f) = Boolmap t f
> update (False, f) (BoolMap t _) = Boolmap t f
"fetch" converts this representation of a total function over k, into
an actual function. The representation of k :-> v might vary
depending on k; Int might use IntMap, (k1,k2) can compose maps:
> instance (MapKey k1, MapKey k2) => MapKey (k1,k2) where
> newtype (k1,k2) :-> v = PairMap (k1 :-> (k2 :-> v))
> ...
> instance (MapKey k1, MapKey k2) => MapKey (Either k1 k2) where
> data (Either k1 k2) :-> v = EitherMap (k1 :-> v) (k2 :-> v)
> ...
This gives you the same benefits as the function approach but without
the terrible performance issues. You do need to write instances for
your types, though, although most can be easily derived from the
instances for pairs, Either, and Integer.
See http://www.haskell.org/haskellwiki/GHC/Indexed_types for more.
-- ryan
-- ryan
> Of course this version of update leaks crazy amounts of memory:
>
>> let bigmap = iterate (update Male 150) classA !! 100000
>> bigmap Male
>
> "bigmap" leaves a huge chain of thunks pointing at each other, which
> can never be freed.
Sure. It's slow, too. If you want a map that you can update, you're
usually much better off with a concrete data structure.
--
Dave Menendez <da...@zednenem.com>
<http://www.eyrie.org/~zednenem/>
Sure, I put up an example at http://ryani.freeshell.org/haskell/gmap.hs
class MapKey k where
data (:->) k :: * -> *
newMap :: (k -> v) -> (k :-> v)
fetch :: (k :-> v) -> (k -> v)
update :: k -> (v -> v) -> (k :-> v) -> (k :-> v)
assign :: k -> v -> (k :-> v) -> (k :-> v)
assign k v m = update k (const v) m
empty :: v -> (k :-> v)
empty = newMap . const
with instances & associated data types:
instance MapKey () where
-- A single value
newtype () :-> v = UMap v
instance MapKey Bool where
-- A value for False and True
data Bool :-> v = BMap v v
instance (MapKey k1, MapKey k2) => MapKey (k1,k2) where
-- A "curried" map
newtype (k1,k2) :-> v = PMap (k1 :-> k2 :-> v)
instance (MapKey k1, MapKey k2) => MapKey (Either k1 k2) where
-- sub-maps for Left k1 and Right k2
data (Either k1 k2 :-> v) = EMap (k1 :-> v) (k2 :-> v)
instance MapKey k => MapKey (Maybe k) where
-- Now we can build up from existing structures!
newtype (Maybe k) :-> v = MaybeM (Either () k :-> v)
instance MapKey k => MapKey [k] where
-- Value for [] and map for (head:tail)
--
-- Note that this includes a recursive ([k] :-> v) map
-- in the pair map (k,[k]) :-> v
data [k] :-> v = ListM v ((k,[k]) :-> v)
instance MapKey Positive where
-- We just convert a positive number into
-- a list of Bools, then make a map of those
newtype Positive :-> v = PosMap ([Bool] :-> v)
instance MapKey Integer where
-- Now an integer is either negative, zero, or positive.
-- So we store a map for negative numbers, a zero value,
-- and a map for positive numbers.
data Integer :-> v = IntMap (Positive :-> v) v (Positive :-> v)
The rest of the class functions are reasonably easy to derive from
their type and these data types.
For example, in
> data Shape = Square | Circle | Triangle
how can I 'iterate' them and apply them all to the same function without
indicating them explicitly?
such as [func Square, func Circle, func Triangle].
Can I use a form similar to the following case in a list instead:
> Numbers = [1,2,3,4,5]
> [func x | x <- Numbers ]
Actually what I want is to obtain all the possible values of a data type
(Shape).
Thank you very much!
Best wishes,
Raeck
_______________________________________________
Beginners mailing list
Begi...@haskell.org
http://www.haskell.org/mailman/listinfo/beginners
> Are there anyway to express the "iterating" of a user-defined data type in
> Haskell?
>
> For example, in
>
> data Shape = Square | Circle | Triangle
>>
>
> how can I 'iterate' them and apply them all to the same function without
> indicating them explicitly?
> such as [func Square, func Circle, func Triangle].
> Can I use a form similar to the following case in a list instead:
>
> Numbers = [1,2,3,4,5]
>>
>
> [func x | x <- Numbers ]
>>
>
> Actually what I want is to obtain all the possible values of a data type
> (Shape).
For "enum" style data, where all the constructors have no arguments, you can
do deriving (Bounded, Enum), so:
data Shape = Square | Circle | Triangle
deriving (Bounded,Enum)
Then:
numbers = [minBound..maxBound] :: [Shape]
Luke
Instead of [func Square, func Circle, func Triangle] you use:
map func [Square, Circle, Triangle].
The list comprehensions should also work:
[func x | x <- [Square, Circle, Triangle]]
Now as for obtaining/generating all values of Shape, the easiest way is
to make Shape an instance of Enum, like this:
data Shape = Square | Circle | Triangle deriving Enum
You can then generate a list of all the values by:
enumFrom Square
You use Square here because it is the first constructor of Shape, and
you want to enumerate them all.
I hope this helps,
Paul
> showAll :: (Eq a, Bounded a, Enum a) => a -> [a]
> showAll a = [minBound..maxBound]::[a]
it keeps saying that I could fix the problem by adding (Enum a) and (Bounded
a) the the context, but I failed when I try.
anything goes wrong?
Thanks!
On Tue, 2008-12-30 at 17:12 +0000, ra...@msn.com wrote:
> Hi, how can I make the following code work? (show all the possible values of
> a type 'a')
>
> > showAll :: (Eq a, Bounded a, Enum a) => a -> [a]
> > showAll a = [minBound..maxBound]::[a]
>
> it keeps saying that I could fix the problem by adding (Enum a) and (Bounded
> a) the the context, but I failed when I try.
>
The problem is the inner annotation, ::[a]. It's not the same a as in
(Eq a, Bounded a, Enum a) => a -> [a], and in Haskell98 it can't be. I'm
not surprised that's confused you! If you remove the inner annotation it
should work fine though.
You can go a step further and make showAll a value rather than a
function:
showAll = [minBound..maxBound]
(I've left out the type annotations, but you can put ":t
[minBound..maxBound]" into ghci or hugs if you want one)
--
Philippa Cowderoy <fli...@flippac.org>
I left the snappy .sigs on the other computer
The bottom 'a' has nothing to do with the 'a' in the type signature.
Your code is equivalent to
> > showAll :: (Eq a, Bounded a, Enum a) => a -> [a]
> > showAll a = [minBound..maxBound]::[b]
Which is not type correct as [minBound..maxBound] :: (Bounded a, Enum a) => [a]
You don't need that type annotation (or the type signature for that matter), so just omit it.
> Hi, how can I make the following code work? (show all the possible values of a type 'a')
>> showAll :: (Eq a, Bounded a, Enum a) => a -> [a]
>> showAll a = [minBound..maxBound]::[a]
What you are really looking for, I think, is a polymorphic value of type [a], where a is some enumerable, bounded type.
allValues :: (Enum a, Bounded a) => [a]
allValues = [minBound .. maxBound]
You can omit the type signature, but then you'll run into the monomorphism restriction (which you'll can turn off with, e.g. -XNoMonomorphismRestriction)
I also found it useful to play around with various expressions and see
what their types where. Especially with things like partial application,
function composition and monadic functions.
Paul
Philippa Cowderoy wrote:
> [-cafe left out]
>
> On Tue, 2008-12-30 at 17:12 +0000, ra...@msn.com wrote:
>> Hi, how can I make the following code work? (show all the possible values of
>> a type 'a')
>>
>>> showAll :: (Eq a, Bounded a, Enum a) => a -> [a]
>>> showAll a = [minBound..maxBound]::[a]
>> it keeps saying that I could fix the problem by adding (Enum a) and (Bounded
>> a) the the context, but I failed when I try.
>>
>
> The problem is the inner annotation, ::[a]. It's not the same a as in
> (Eq a, Bounded a, Enum a) => a -> [a], and in Haskell98 it can't be. I'm
> not surprised that's confused you! If you remove the inner annotation it
> should work fine though.
>
> You can go a step further and make showAll a value rather than a
> function:
>
> showAll = [minBound..maxBound]
>
> (I've left out the type annotations, but you can put ":t
> [minBound..maxBound]" into ghci or hugs if you want one)
>