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<javascript:>
> > 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. 
 

>
> ; nREPL 0.1.7
> user> 
> #<Namespace monads.core>
> monads.core> (defn mc [x]
>                (>>= (return x)
>                     (fn [a] (>>= (return (inc a))
>                                  (fn [b]
>                                      (return (+ x (* 2 b))))))))
> #'monads.core/mc
> monads.core> (def m* (mc 5))
> #'monads.core/m*
> monads.core> (require '[monads.identity :as i] '[monads.maybe :as m])
> nil
> monads.core> (run-monad i/m m*)
> 17
> monads.core> (run-monad m/m m*)
> #<Just 17>
> monads.core> 
>
> m* is already defined in a completely agnostic way before it's run. I 
> thought i had already demonstrated that in my previous email when I defined 
> mc as (>>= (return 3) (f inc)), prior to interpreting it in the context of 
> any particular monad.
>  
>
>> Regarding monadic laws, which one exactly demands that you cannot change 
>> the monad (not counting the fact that haskell's implementation does it that 
>> way)? Here are the laws, in Haskell:
>>
>> return a >>= k  =  k a
>> m >>= return    =  m
>> m >>= (\x -> k x >>= h)  =  (m >>= k) >>= h
>>
>> It seems to me the laws are still satisfied if you keep changing monads 
>> in each bind (if compiler is not restricting it, as is the case with 
>> Haskell but not with Clojure).
>>
>  
> 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... 

(>>= (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
Haskell compiler would complain wildly, but there is no Haskell compiler in 
my REPL :)

Can I prove it? NO, I didn't try. As you say, most of the time you will 
work in the same monad. Since Clojure is dynamic, the programmer is 
expected to take an extra care and test that everything works as expected. 
But, it seems to me that, even if the monad change, (in most cases?) it 
will still work...

 

>  
>
>> On Wednesday, July 3, 2013 1:19:10 AM UTC+2, Ben wrote:
>>
>>> IMO you *always* want the monad to stay the same---the laws describing 
>>> monadic computations don't account for swapping the things out midstream, 
>>> at any rate. And it pays to be able to define monadic computations without 
>>> having to explicitly pass around a token to serve as "the current monad".
>>>
>>> FWIW, you *can* directly translate that function into clojure:
>>>
>>> monads.core> (defn f [g] (comp return g g))
>>> #'monads.core/f
>>> monads.core> (require '[monads.state :as st])
>>> nil
>>> monads.core> (st/run-state (>>= get-state (f inc)) 5)
>>> #<Pair [7 5]>
>>> monads.core> (require '[monads.list :as l])
>>> nil
>>> monads.core> (require '[monads.maybe :as m])
>>> nil
>>> monads.core> (def mc (>>= (return 3) (f inc)))
>>> #'monads.core/mc
>>> monads.core> (run-monad m/m mc)
>>> #<Just 5>
>>> monads.core> (run-monad l/m mc)
>>> (5)
>>> monads.core> (st/run-state mc {})
>>> #<Pair [5 {}]>
>>>
>>> You just have to take a different approach to how the results are 
>>> executed. (This is with this lib: https://github.com/bwo/monads)
>>>
>>>
>>>
>>> On Tue, Jul 2, 2013 at 4:03 PM, Dragan Djuric <drag...@gmail.com> wrote:
>>>
>>>> pure function, defined in applicative, is equivalent to return (In 
>>>> Haskell, in Fluokitten there is only pure).
>>>>
>>>> I think I understand what is your question now. Since Clojure does not 
>>>> support polymorphysm based on the returning argument you cannot translate 
>>>> that Haskell code exactly. For such a case (when you want to keep 
>>>> operating 
>>>> in the same monad without knowing which one it is), a you have to provide 
>>>> an argument for m in f (but that's how Clojure works :), and then apply it 
>>>> partially or curry it:
>>>>
>>>> (defn f [m g] (comp (pure m) g g))
>>>>
>>>> (def c+ (curry +))
>>>>
>>>> (bind [1 2 3] (f [] (c+ 2))
>>>> or
>>>> (>>= [1 2 3] (f [] (c+ 2))
>>>>
>>>> If [] really hurts your aesthetic views maybe a macro (bind* or mdo) 
>>>> would help, since instead of [], any vector, let's say [1 2 3] would do, 
>>>> but then, it's a special case when you actually want the monad to stay the 
>>>> same.
>>>>
>>>> Thank you for helpful comments, BTW :)
>>>>
>>>> On Wednesday, July 3, 2013 12:03:45 AM UTC+2, Ben wrote:
>>>>
>>>>> e.g., I'm not sure how to define the function "f" here:
>>>>>
>>>>> $ ghci
>>>>> GHCi, version 7.4.1: http://www.haskell.org/ghc/  :? for help
>>>>> Loading package ghc-prim ... linking ... done.
>>>>> Loading package integer-gmp ... linking ... done.
>>>>> Loading package base ... linking ... done.
>>>>> Prelude> let f :: (Monad m) => (a -> a) -> a -> m a  ; f g  = return . 
>>>>> g . g
>>>>> Prelude> Just 4 >>= f (2+)
>>>>> Just 8
>>>>> Prelude> [[1]] >>= f (2:)
>>>>> [[2,2,1]]
>>>>> Prelude> import Control.Monad.State
>>>>> Prelude Control.Monad.State> runState (get >>= f (+4)) 4
>>>>> Loading package transformers-0.2.2.0 ... linking ... done.
>>>>> Loading package mtl-2.0.1.0 ... linking ... done.
>>>>> (12,4)
>>>>> Prelude Control.Monad.State> 
>>>>>
>>>>>
>>>>>
>>>>> On Tue, Jul 2, 2013 at 2:45 PM, Ben Wolfson <wol...@gmail.com> wrote:
>>>>>
>>>>>> I did look at the docs and I don't really get how to return a monadic 
>>>>>> value in the right monad, the way "return" does automatically. All the 
>>>>>> examples I saw have something like "vector" or "atom" or what-have-you.
>>>>>>
>>>>>>
>>>>>> On Tue, Jul 2, 2013 at 2:41 PM, Dragan Djuric <drag...@gmail.com>wrote:
>>>>>>
>>>>>>> No, the second argument to bind only needs to be a function that 
>>>>>>> takes a plain value and return a monadic value; you do not need to 
>>>>>>> specify 
>>>>>>> anything explicitly and it does not need to know what kind of monad it 
>>>>>>> is 
>>>>>>> operating on. Whatever that function returns will be a monad that the 
>>>>>>> eventual second bind will operate on.
>>>>>>> Moreover, Fluokitten supports vararg bind, so the function is 
>>>>>>> actually the last argument of bind in general case; it is the second 
>>>>>>> argument only if there are two args.
>>>>>>>
>>>>>>> Please note that Fluokitten does not have a built-in mdo (a 
>>>>>>> syntactic sugar for nested binds) for now. The reason is that Clojure 
>>>>>>> itself has native constructs that do many stuff that Haskell's do does, 
>>>>>>> so 
>>>>>>> I am not yet sure why and if it would be useful, and if I add it how to 
>>>>>>> make it non-awkward. Of course, I am open to suggestions.
>>>>>>> Also note that Fluokitten is not monad-centric, it has functors, 
>>>>>>> applicatives, etc and I plan to add more categorical concepts, so It is 
>>>>>>> different in that regard from other monadic Clojure libraries. That's 
>>>>>>> why I 
>>>>>>> would like to suggest reading the docs, most of the stuff is 
>>>>>>> significantly 
>>>>>>> different from other libs, and more similar (but simpler, due to the 
>>>>>>> lack 
>>>>>>> of legacy) to Haskell's categorical stuff.
>>>>>>>
>>>>>>>
>>>>>>> On Tuesday, July 2, 2013 9:15:10 PM UTC+2, Ben wrote:
>>>>>>>
>>>>>>>> I haven't played around with this but it looks as if the second 
>>>>>>>> argument to bind needs to know what kind of monad it's operating in, 
>>>>>>>> is 
>>>>>>>> that right? Would it be possible to write agnostic functions like this 
>>>>>>>> in 
>>>>>>>> this lib?
>>>>>>>>
>>>>>>>> monads.core> (defn tst-reader [f]
>>>>>>>>                (mdo env <- ask
>>>>>>>>                     v <- (lift (f env))
>>>>>>>>                     (return (println "here I am"))
>>>>>>>>                     (return v)))
>>>>>>>> #'monads.core/tst-reader
>>>>>>>> monads.core> (require '[monads.reader :as r] '[monads.identity :as 
>>>>>>>> i] '[monads.state :as st] '[monads.error :as e])
>>>>>>>> nil
>>>>>>>> monads.core> (r/run-reader-t (r/t i/m) (tst-reader (comp return 
>>>>>>>> inc)) 5)
>>>>>>>> here I am
>>>>>>>> 6
>>>>>>>> monads.core> (r/run-reader-t (r/t e/m) (tst-reader (fn [_] 
>>>>>>>> (throw-error "early exit"))) 5)
>>>>>>>> #<Either [:left early exit]>
>>>>>>>> monads.core> (st/run-state (r/run-reader-t (r/t st/m) (tst-reader 
>>>>>>>> (fn [env] (>> (modify #(assoc % :env env)) (return (dec env))))) 5) {})
>>>>>>>> here I am
>>>>>>>> #<Pair [4 {:env 5}]>
>>>>>>>> monads.core> 
>>>>>>>>
>>>>>>>> ?
>>>>>>>>
>>>>>>>>
>>>>>>>> On Tue, Jul 2, 2013 at 11:07 AM, Dragan Djuric 
>>>>>>>> <drag...@gmail.com>wrote:
>>>>>>>>
>>>>>>>>> I am pleased to announce a first public release of new (and 
>>>>>>>>> different) "monads and friends" library for Clojure.
>>>>>>>>> Extensive *documentation* is at http://fluokitten.**uncomplicate**
>>>>>>>>> **.org <http://fluokitten.uncomplicate.org>
>>>>>>>>>
>>>>>>>>> Fluokitten is a Clojure library that implements category theory 
>>>>>>>>> concepts, such as functors, applicative functors, monads, monoids 
>>>>>>>>> etc. in 
>>>>>>>>> idiomatic Clojure.
>>>>>>>>>
>>>>>>>>> Main project goals are:
>>>>>>>>>
>>>>>>>>>    - Fit well into idiomatic Clojure - Clojure programmers should 
>>>>>>>>>    be able to use and understand Fluokitten like any regular Clojure 
>>>>>>>>> library.
>>>>>>>>>    - Fit well into Haskell monadic types conventions - 
>>>>>>>>>    programmers should be able to reuse existing widespread monadic 
>>>>>>>>> programming 
>>>>>>>>>    know-how and easily translate it to Clojure code.
>>>>>>>>>    - Be reasonably easy to learn - the code from the existing 
>>>>>>>>>    books, articles and tutorials for learning monadic programming, 
>>>>>>>>> which is 
>>>>>>>>>    usually written in Haskell should be easily translatable to 
>>>>>>>>> Clojure with 
>>>>>>>>>    Fluokitten.
>>>>>>>>>    - Offer good performance.
>>>>>>>>>
>>>>>>>>> Please give us your feedback, and we would also love if anyone is 
>>>>>>>>> willing to help, regardless of previous experience, so please *get 
>>>>>>>>> involved*. There are lots of things to be improved:
>>>>>>>>>
>>>>>>>>>    - If you are a native English speaker, i would really 
>>>>>>>>>    appreciate if you can help with correcting the English on the 
>>>>>>>>> Fluokitten 
>>>>>>>>>    site and in the documentation.
>>>>>>>>>    - Contribute your example code (your own or the ports from 
>>>>>>>>>    Haskell tutorials) to be added to Fluokitten tests.
>>>>>>>>>    - Contribute articles and tutorials.
>>>>>>>>>    - Do code review of the Fluokitten code and suggest 
>>>>>>>>>    improvements.
>>>>>>>>>    - If you find bugs, report them via Fluokitten issue tracker.
>>>>>>>>>    - If you have any additional suggestion, contact us here: 
>>>>>>>>>    http://fluokitten.**uncomplicate****.org/articles/**
>>>>>>>>>    
>>>>>>>>> community.html<http://fluokitten.uncomplicate.org/articles/community.html>
>>>>>>>>>  
>>>>>>>>>
>>>>>>>>>  -- 
>>>>>>>>> -- 
>>>>>>>>> You received this message because you are subscribed to the Google
>>>>>>>>> Groups "Clojure" group.
>>>>>>>>> To post to this group, send email to clo...@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+u...@**googlegroups.com
>>>>>>>>>
>>>>>>>>> For more options, visit this group at
>>>>>>>>> http://groups.google.com/**group****/clojure?hl=en<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+u...@**googlegroups.com.
>>>>>>>>>
>>>>>>>>> For more options, visit https://groups.google.com/**grou****
>>>>>>>>> ps/opt_out <https://groups.google.com/groups/opt_out>.
>>>>>>>>>  
>>>>>>>>>  
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> -- 
>>>>>>>> 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 clo...@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+u...@**googlegroups.com
>>>>>>> For more options, visit this group at
>>>>>>> http://groups.google.com/**group**/clojure?hl=en<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+u...@**googlegroups.com.
>>>>>>> For more options, visit 
>>>>>>> https://groups.google.com/**grou**ps/opt_out<https://groups.google.com/groups/opt_out>
>>>>>>> .
>>>>>>>  
>>>>>>>  
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> -- 
>>>>>> 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]
>>>>>>
>>>>>>  
>>>>>
>>>>>
>>>>> -- 
>>>>> 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 clo...@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+u...@**googlegroups.com
>>>> For more options, visit this group at
>>>> http://groups.google.com/**group/clojure?hl=en<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+u...@**googlegroups.com.
>>>> For more options, visit 
>>>> https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out>
>>>> .
>>>>  
>>>>  
>>>>
>>>
>>>
>>>
>>> -- 
>>> 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 clo...@googlegroups.com<javascript:>
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com <javascript:>
>> 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+u...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/groups/opt_out.
>>  
>>  
>>
>
>
>
> -- 
> 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.


Reply via email to