[clean-list] Understanding Generics
Arjen van Weelden
A.vanWeelden at cs.ru.nl
Tue Aug 1 09:55:10 MEST 2006
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/
>
>
More information about the clean-list
mailing list