On Mon, Apr 21, 2008 at 10:58 PM, Jonathan Cast <[EMAIL PROTECTED]> wrote: > I must have failed to communicate well. To me, the point of giving a class > a name is that then you can write a program that is parametric over the > elements of that class. Knowing that I can implement monads in Ruby doesn't > impress me nearly as much as knowing that I can implement mapM does. > Haskell has me addicted to code reuse (mapM) the way the rest of the > programming world is addicted to design patterns (monads). What I mean by > `encoding Num and Monad' is that you can do something like this: > > sum = foldr (+) 0 > sequence = foldr (liftM2 (:)) (return []) > > I don't know of any language that is dynamically typed and also can encode > `return' or `0' in a way that lets those examples work. Statically typed > languages where it works are rare, even. Haskell gives up a fair amount of > control by making these things implicit, which is what I think you're > running up against --- but I think it gets something useful and non-trivial > to acheive in return.
I think ruby generally solves this problem via duck-typing; instead of the cast happening in the (implicit) fromInteger call in sum above, instead the cast happens in the function with more information via a call to otherclass#to_whatever_i_am. You can do something like this: class Frob attr_reader :val def initialize(i) @val = i end def to_frob self end def +(rhs) rhsF = rhs.to_frob Frob.new(rhsF.val + @val) end end class Integer def to_frob Frob.new(self) end end class Array def sum foldl(0) {|acc,x| acc + x} end def foldl(z) each {|x| z = yield(z,x)} z end end irb(main):055:0> [1,2,3].sum => 6 irb(main):057:0> [1,2,3].map {|x| Frob.new(x)}.sum => #<Frob:0x2b65cf0 @val=6> > I'll agree with this point. I've complained, concretely, about the lack of > instances for (some) standard types before. (STM is actually a rather bad > offender here; it's lacking MonadPlus, as well, despite the specific > observation in the paper that it has the right signature for that class.) Actually: GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help Loading package base ... linking ... done. Prelude> :m Control.Monad Control.Monad.STM Prelude Control.Monad.STM Control.Monad> :i STM ... instance MonadPlus STM -- Defined in Control.Monad.STM > When can we discharge a MaybeInstance context? On any concrete type. Like Typeable should be :) The compiler then determines whether that type is an instance of the class and provides the appropriate dictionary if applicable. > Having the | Show a test suddenly trip from False to True because some > other module imported Text.Show.Functions sounds like an odd change to me. > At any rate, it scares me enough to make me oppose the idea. I see the worry now. I think this is more of a problem with orphan instances; are orphan instances considered to be a valuable enough feature to avoid potentially more powerful constructs? Maybe there is a better solution to the "I have class C from library X and type T from library Y and I want to make them play nice together" problem than orphan instances. > class Forceable alpha where > seq :: alpha -> beta -> beta > > Instances derived automatically by the compiler, when possible, for every > type (like Typeable should be). We can omit functions if desired (I don't > remember why I thought this was a good idea). When you say > > f :: alpha -> beta > > or > > f :: C alpha => alpha -> beta > > The compiler adds implicit Forceable constraints on alpha and beta. But, > if you say > > f :: !Forceable alpha => alpha -> beta > > The compiler leaves the Forceable alpha constraint off. Then you can say > > build :: (forall c. !Forceable c => (a -> c -> c) -> c -> c) -> [a] > > And the foldr/build law is still sound. This seems like a really interesting idea. -- ryan _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe