[clean-list] Understanding Generics

Arjen van Weelden A.vanWeelden at cs.ru.nl
Mon Jul 24 13:12:43 MEST 2006


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.

cheers,
	Arjen

Alexsandro Soares wrote:
> Hi all,
> 
>    I'm trying to figure out how to implement a generic
> version of the function "sub". This function takes an
> element and returns a list of this element and all its
> subtrees. Examples:
> 
>   sub [1,2,3] = [[1,2,3], [2,3], [3], []] 
>   sub (B (L 1) (L 2)) = [(B (L 1) (L 2)), (L 1), (L
> 2)]
> 
>   Reading the Clean manual I couldn't understand how
> to use generics for this case. Can anyone help me? 
> 
> Cheers,
>   Alex
>    
> P.S.:  The non-generic implemention would be
> 
> ---- Sub.icl
> ------------------------------------------
> module Sub
> import StdGeneric, StdEnv
> 
> :: Tree a = L a | B (Tree a) (Tree a)
> :: List a = Nil | Cons a (List a)
> 
> t1 = B (L 1) (L 2)
> l1 = Cons 1 (Cons 2 (Cons 3 Nil))
> 
> subTree :: (Tree a) -> [(Tree a)]
> subTree (L a) = [L a]
> subTree (t=:(B l r)) = [t:subTree l] ++ subTree r
> 
> subList :: (List a) -> [(List a)]
> subList Nil = [Nil]
> subList (l=:(Cons x xs)) = [l : subList xs]
> 
> -----------------------------------------------------
> 
> 
> 	
> 
> 
> 
> 	
> 		
> _______________________________________________________ 
> Você quer respostas para suas perguntas? Ou você sabe muito e quer compartilhar seu conhecimento? Experimente o Yahoo! Respostas !
> http://br.answers.yahoo.com/
> _______________________________________________
> clean-list mailing list
> clean-list at science.ru.nl
> http://mailman.science.ru.nl/mailman/listinfo/clean-list
-------------- next part --------------
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)


More information about the clean-list mailing list