On Wed, 2007-07-25 at 03:00 -0700, Erick Tryzelaar wrote: > More strangeness. I managed to get the function arrow working with this:
Really?? That's just awesome! > /////////////////////////////// > #import <flx.flxh> > > typeclass Arrow[M: TYPE->TYPE->TYPE] > { > virtual fun arrow[a, b]: (a->b) -> M a b; > virtual fun bind[a, b, c]: M a b -> M b c -> M a c; > virtual fun first[a, b, c]: M a b -> M (a*c) (b*c); > virtual fun second[a, b, c]: M a b -> M (c*a) (c*b); > virtual fun parallel[a, b, c, d]: M a c -> M b d -> M (a*b) (c*d); > virtual fun split[a, b, c]: M a b -> M a c -> M a (b*c); > } > > typedef fun Fun (a:TYPE) (b:TYPE): TYPE => a->b; > > instance Arrow[the Fun] { > fun arrow[a, b] (f:a->b): a->b => f; > fun bind[a, b, c] (f:a->b) (g:b->c): a->c => (fun (x:a) => g $ f x); > fun first[a, b, c] (f:a->b) => > (fun (x:a, y:c) => (f x, y)) > ; > fun second[a, b, c] (f:a->b) => > (fun (x:c, y:a) => (x, f y)) > ; > > fun parallel[a, b, c, d] (f:a->c) (g:b->d) => > (fun (x:a, y:b) => (f x, g y)) > ; > > fun split[a, b, c] (f:a->b) (g:a->c) => > (fun (x:a) => (f x, g x)) > ; > } > open Arrow[the Fun]; > > val x = arrow (fun (x:int) => x + 5); > val y = bind x x; > > proc print (x:int, y:int) { print "("; print x; print ", "; print y; > print ")"; } > > print $ first[int,int,int] x $ (5, 6); endl; > print $ second[int,int,int] x $ (5, 6); endl; > print $ parallel x y $ (5, 6); endl; > print $ split x y $ 5; endl; > ///////////////////// > > > But I'm not sure why these need the [int,int,int]: > > print $ first[int,int,int] x $ (5, 6); endl; > print $ second[int,int,int] x $ (5, 6); endl; > > parallel and split don't seem to need them... Something to do with the fact that types are synthesised bottom up. Here: fun parallel[a, b, c, d] (f:a->c) (g:b->d) => a,b,c,d can all be deduced given 2 arguments -- I'm surprised this works, it certainly won't if you try a partial application (make a new function curried on first argument only). However: fun first[a, b, c] (f:a->b) => doesn't specify 'c' in the argument, so it can't be deduced. Thus, you must specify c. Remember, unlike say Haskell .. Felix supports overloading. However not for type function BECAUSE they're actually represented as a type lambda, which is a 'value' :) Because of overloading, recursive functions would be impossible to type unless all the argument types are known, because you don't know which function is being called in the recursion unless you know the types of its arguments, and you can't know that if they depend on parameters which don't have specified types. Type variables are the same, however it is very confusing because the value of a type variable which is a parameter can be instantiated to a term containing other type variables from the calling context. Here the usual terminology of 'free' and 'bound' variable is exceptionally confusing.. a free variable is treated as a fixed constant (and so is frozen or bound) whereas a bound variable is treated as something actually variable, or 'free to be vary'.. :) :) It all depends on the context, that is, how much of the 'term' you're examining. If you look inside the binders which make a type variable a bound variable the variable suddenly becomes free because the binder is stripped off and pushed into the environment. Of course, the environment provides a binding for it then, so it is anything but free .. :) -- John Skaller <skaller at users dot sf dot net> Felix, successor to C++: http://felix.sf.net ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language