[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