[clean-list] Understanding Generics

Arjen van Weelden A.vanWeelden at cs.ru.nl
Tue Aug 1 15:09:07 MEST 2006


Sorry for the reply to self.

There is another issue with this not so elegant solution:
it give a run-time error on lists of lists, e.g., [[Int]].
Alex, what do you want in this case?
What should be the result of sub [[1, 2], [3], [4, 5, 6]]?

regards,
	Arjen

Arjen van Weelden wrote:
> Hi Alex,
> 
> It is my fault, I didn't make gsub lazy enough.
> To fix it, replace
> generic gsub a :: !String a -> (!(Rep -> a), Rep, ![Rep])
> with
> generic gsub a :: !String a -> (!(Rep -> a), Rep, [Rep])
> 
> Please remember that this is neither an elegant nor a typical generic 
> function. I don't recommend its usage. I've not been able to find an 
> elegant solution with a type like a -> [a].
> 
> kind regards,
>     Arjen
> 
> Alexsandro Soares wrote:
>> Hi Arjen,
>>
>>    Thank you again for your answer.
>>    If I try to define the following type
>>       :: MyTree a = B (MyTree a) (MyTree a) | L a | None
>> and then I try the following
>>
>>     Start = sub (B (L 1) (L 2))
>>
>> the compiler complains with
>>
>>   [(B (L 1) (L 2)),Run time error, rule
>> '<case>[line:80];32;113' in module 'GenSub' does not
>> match.
>>
>>    If I change the order in type definition to
>>
>>    :: MyTree a =  L a | None | B (MyTree a) (MyTree a)
>>
>>    then it works well and give me the following answer
>>  
>>
>>        [(B (L 1) (L 2)),(L 1),(L 2)]
>>
>>    I can't understand this behaviour. Do you have any
>> explanation?
>>
>>   Regards,
>>   Alex
>>
>>
>>
>>
>> --- Arjen van Weelden <A.vanWeelden at cs.ru.nl>
>> escreveu:
>>
>>> Hi Alex,
>>>
>>> This was not as easy as I expected. The problem is
>>> that you have to gather values of a certain type, but you cannot
>>> combine them in PAIRs.
>>> If this is your first attempt at a generic function,
>>> please use more simple (c.f. Libraries\Generics) examples to learn
>>> from.
>>>
>>> Have a look at the attached solution. Detecting the
>>> values of a certain type is done in the {|OBJECT|} instance using the
>>> name of the type as a String. Gathering the values is done using the Rep
>>> type, which can contain any type by mimicking its generic structure,
>>> and "parsing" them back to the original type. It has been made lazy
>>> enough to get the "parser" without passing a real value, required in
>>> the {|EITHER|} instance.
>>>
>>> module GenSub
>>>
>>> import StdList, StdFunc, StdString, StdGeneric
>>>
>>> :: Tree a = L a | B (Tree a) (Tree a)
>>>
>>> subTree :: (Tree a) -> [Tree a]
>>> subTree t=:(B l r) = [t:subTree l] ++ subTree r
>>> subTree (L a) = [L a]
>>>
>>> subList :: [a] -> [[a]]
>>> subList l=:[_:xs] = [l:subList xs]
>>> subList _ = [[]]
>>>
>>> sub :: !a -> [a] | gsub{|*|} a
>>> sub x = map p [y:ys]
>>> where
>>>     (p, y, ys) = gsub{|*|} "" x
>>>
>>> Start = (subList [1, 2, 3], subTree (B (L 1) (L 2)),
>>> "\n", sub [1, 2, 3], sub (B (L 1) (L 2)))
>>>
>>> derive bimap [], (,,)
>>> derive gsub [], Tree
>>>
>>> :: Rep = Pair !Rep !Rep | Left !Rep | Right !Rep |
>>> Unit | Int !Int
>>>
>>> generic gsub a :: !String a -> (!(Rep -> a), Rep,
>>> ![Rep])
>>>
>>> gsub{|Int|} _ i = (\(Int i) -> i, Int i, [])
>>>
>>> gsub{|UNIT|} _ _ = (\Unit -> UNIT, Unit, [])
>>>
>>> gsub{|CONS of gcd|} sub_a name cons = (CONS o px, x,
>>> xs) where
>>>     (px, x, xs) = sub_a name (case cons of CONS a -> a)
>>>
>>> gsub{|OBJECT of gtd|} sub_a name object = (OBJECT o
>>> px, x, if (gtd.gtd_name == name) [x:xs] xs)
>>> where
>>>     (px, x, xs) = sub_a (if (name == "") gtd.gtd_name
>>> name) (case object of OBJECT a -> a)
>>>     
>>> gsub{|EITHER|} sub_a sub_b name e = (p, r, rs)
>>> where
>>>     (r, rs) = case e of
>>>         LEFT a             # (_, x, xs) = sub_a name a
>>>             -> (Left x, xs)
>>>         RIGHT b             # (_, y, ys) = sub_b name b
>>>             -> (Right y, ys)
>>>     p (Left r)         # (px, _, _) = sub_a name (case e of LEFT a -> a)
>>>         = LEFT (px r)
>>>     p (Right r)         # (py, _, _) = sub_b name (case e of RIGHT b 
>>> -> b)
>>>         = RIGHT (py r)
>>>
>>> gsub{|PAIR|} sub_a sub_b name pair = (\(Pair r1 r2)
>>> -> PAIR (px r1) (py r2), Pair x y, xs ++ ys)
>>> where
>>>     (px, x, xs) = sub_a name (case pair of PAIR a _ ->
>>> a)
>>>     (py, y, ys) = sub_b name (case pair of PAIR _ b ->
>>> b)
>>>
>>
>>
>>
>>        
>> _______________________________________________________ Novidade no 
>> Yahoo! Mail: receba alertas de novas mensagens no seu celular. 
>> Registre seu aparelho agora! http://br.mobile.yahoo.com/mailalertas/  
>>
> _______________________________________________
> clean-list mailing list
> clean-list at science.ru.nl
> http://mailman.science.ru.nl/mailman/listinfo/clean-list


More information about the clean-list mailing list