On Wed, Jul 3, 2013 at 12:32 AM, Dragan Djuric <draga...@gmail.com> wrote:
> > > On Wednesday, July 3, 2013 2:06:34 AM UTC+2, Ben wrote: > >> On Tue, Jul 2, 2013 at 4:33 PM, Dragan Djuric <drag...@gmail.com> wrote: >> >>> And in this case you have to explicitly specify which monad you want to >>> use, every time you call bind. I understand that in some case it might be a >>> preferred way, but in my opinion for most cases that I care about I prefer >>> it the other way. >> >> >> No, you don't. You don't have to specify the monad you want to use until >> you actually want to use it: >> > > Unless you need to use two or more different monads in that function, in > which case I don't see now would you do that at all. And, you have to > structure the code a bit awkwardly for clojure, and have to say > specifically, I want such and such monad type, and run it with a runner. > I'm not saying that that is not good option. Clojure has its features and > some compromise has to be made. I just prefer the sort of compromises I > made for Fluokitten to the sorts of compromises made by other libraries. > Well, my *very first* message demonstrated how to do that in a generic way. (defn tst-reader [f] (mdo env <- ask v <- (lift (f env)) (return (println "here I am")) (return v))) You use more than one monad here in the same way you do it in Haskell: using a monad transformer, lifting from one to the other. Here you can do it without specifying *either* layer of the stack (as long as the first supports "ask"). You *never* have to say "I want such and such monad type" while you're writing the function, until you actually run it, and the same computation can be run with multiple different types (again, my first message demonstrated this, embedding arbitrary different effects including early exit and mutable state into that function without modifying it at all). As far as I can tell, with Fluokitten you *always* do. I suppose that may be right: you're supposed to verify that the laws obtain for a putative monad; they don't come for free just by calling something a monad. Allowing >>= to have the type m a -> (a -> n b) -> n b just means that you can't verify that yours obeys the laws. If you get to choose the type of "return", even the second one is up for grabs! It does seem somewhat odd to me to advertise the package as being familiar to Haskellers and to employ category-theoretic concepts and then to be so blasé about the definition of a monad. (I wonder if you can get away with this changing of type at all if you define bind in terms of fmap and join). > Here is how the laws are specified (and tested) in Fluokitten (writing > from the top of my head so please excuse me if I mess up something): > > (def return (pure [])) ;;This def is to make it more familiar for those > who already read this tread, it is not actually in fluokitten tests. > > (def k (comp return foo bar baz)) ;; note the agnostic return. There are > ways in Clojure to change what is it bound for, but I won't go into that > here, It does not seem that important to me now. The point is, fluokitten > supports it... > That is not an agnostic return: it works only for vectors. You could change what it's bound for with, I suppose, with-redefs? > > (>>= (return a) k) > => (k a) > > (>>= [1 2 3] return) > => m > > (>>= [1 2 3] (fn [x] (bind (k x) h))) > => (>>= m k h) > > So, if monad stays the same, everything is nice and tidy and close enough > to Clojure and Haskell. > > Now, what would happen if monad changes after the bind? > > The first law does not constrain it > The second does not too, since it says what happens when you bind with > (pure m) not (pure n) > The third, associativity, will also be satisfied > Really? Let's find out! uncomplicate.fluokitten.core> (def return (pure [])) #'uncomplicate.fluokitten.core/return uncomplicate.fluokitten.core> (def k (comp return inc (partial * 2))) uncomplicate.fluokitten.core> (>>= (>>= [1 2 3] k) (fn [x] (atom (inc x)))) IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Atom clojure.lang.RT.seqFrom (RT.java:505) uncomplicate.fluokitten.core> (>>= [1 2 3] (fn [x] (>>= (k x) (fn [y] (atom (inc y)))))) IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Atom clojure.lang.RT.seqFrom (RT.java:505) I guess you're right: they are the same. However, I think this, regarding the second law, is telling: "The second does not too, since it says what happens when you bind with (pure m) not (pure n)" *all* the laws only say what happen when you stay within the same monad, because the types the laws give to >>= and return *require* that. -- Ben Wolfson "Human kind has used its intelligence to vary the flavour of drinks, which may be sweet, aromatic, fermented or spirit-based. ... Family and social life also offer numerous other occasions to consume drinks for pleasure." [Larousse, "Drink" entry] -- -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.