Monads compared to InputRanges?

Max Klyga email at domain.com
Tue Dec 3 23:13:34 PST 2013


On 2013-12-04 01:53:39 +0000, Shammah Chancellor said:

> On 2013-12-03 23:49:47 +0000, Max Klyga said:
> 
>> On 2013-12-03 23:02:13 +0000, Shammah Chancellor said:
>> 
>>> On 2013-12-03 21:51:20 +0000, Max Klyga said:
>>> 
>>>> On 2013-12-03 02:45:44 +0000, Shammah Chancellor said:
>>>> 
>>>>> I'm not particularly familiar with the syntax being used in the variet 
>>>>> of monad examples.   I'm trying to figure out how this is different 
>>>>> from UFCS on InputRanges.   It seems like std.algorithm implements 
>>>>> something which accomplished the same thing, but much easier to 
>>>>> understand?
>>>>> 
>>>>> Can somebody maybe do a compare and contrast for me?
>>>>> 
>>>>> -Shammah
>>>> 
>>>> Monads and input ranges are different things. I'll try to briefly 
>>>> explain monads. Hope this will not worsen the situation by being too 
>>>> confusing.
>>>> 
>>>> InputRanges provide a generic way for iterating over something.
>>>> 
>>>> UFCS can be used to create a range interface on things that do not provide it.
>>>> 
>>>> Monads are an abstraction for composing things within some context 
>>>> (concatenating lists, composing operations on nullable values, 
>>>> composing asynchronous operations). That sounds a bit too general and 
>>>> vague, because it is. One can think about as a design pattern.
>>>> Monad has two operations:
>>>>  - make a monad out of a value
>>>>  - apply a function that takes a value and returns a new monad of the 
>>>> same kind to value inside a monad
>>>> 
>>>> second operation has a different meaning for different monad kinds but 
>>>> generally it means 'execute this code within current context'
>>>> 
>>>> for nullable values this means 'execute only if there exist a value'
>>>> for asynchronous operations this means 'execute this when the value is ready'
>>>> 
>>>> This operation is commonly named 'bind' or 'flatMap'
>>>> 
>>>> Some languages provide syntax sugar for monads (Scala's for, Haskell's do)
>>>> Monads are easier to understand once you've seen enough examples of 
>>>> things that are monads.
>>>> 
>>>> Suppose you have a list of movies and want to produce a list of names 
>>>> of all actors stating in those movies.
>>>> In scala you would typically write something like this:
>>>> 
>>>> 	for (movie <- movies; actor <- movie.actors) yield actor.name
>>>> 
>>>> Compiler rewrites that to
>>>> 
>>>> 	movies.flatMap(movie => movie.actors).map(actor => actor.name)
>>>>                           ^
>>>>                            ---------- this function takes a list 
>>>> element and returns a new list, effectively creating a list of lists 
>>>> and then flattening it by concatenating all the lists into one, hence 
>>>> the name 'flatMap'. It transforms and then flattens.
>>>> 
>>>> Another popular example for Monads are optional values (similar to 
>>>> nullables but forcing you to check for presence of value and explicitly 
>>>> avoiding null dereferencing)
>>>> 
>>>> A common pattern for working with optional values is returning null 
>>>> from your function if your input is null
>>>> 
>>>> So if say we are parsing JSON and we want to process only values that 
>>>> contain certain field, that in turn contains another field. Example in 
>>>> pseudo-scala:
>>>> 
>>>> 	for (value <- json.get("value"); // type of value is Option(JsonNode) 
>>>> meaning that actual json node might be absent
>>>> 	       anotherValue <- value.get("another")) // this is executed only 
>>>> if value is present
>>>> 		doSomethingFancy(anotherValue) // ditto
>>>> 
>>>> and again, compiler will rewrite this into
>>>> 
>>>> 	json.get("value").flatMap(value => 
>>>> value.get("another")).foreach(anotherValue => 
>>>> doSomethingFancy(anotherValue))
>>>> 
>>>> Once again we see that flat map is used. The pattern is same - get the 
>>>> value out of the box, transform it to another box of the same kind in 
>>>> the context meaningful for this particular box kind
>>>> 
>>>> So the main benefit is being able to compose things in a consistent 
>>>> way. Once you grasp the whole idea its fun finding out that some thing 
>>>> you've been doing can be viewed as a monad. People created quite a lot 
>>>> of different monads to this date.
>>> 
>>> 
>>> I get the gist of that, but it seems like the range concept with UFCS 
>>> provides the same thing? E.G.  range.map().flatten().map()?
>>> 
>>> Does it really not accomplish the same thing -- am I missing some key 
>>> point of monads?
>> 
>> You look only at the syntax side of the question.
>> 
>> range.map(...).flatten.map(...) might look similar and it could be 
>> possible to squeeze monads to work with this api, but the thing is that 
>> not every monad could provide a meaningful map function and as a whole 
>> calling flatten after every map is a bit tiresome.
>> 
>> That may work for some monads, like List, because its effectively a range.
>> It will also work for Maybe monad. It could be viewed as a range of 0 
>> or 1 elements.
>> But things get bad when we try to define other monads in terms of range 
>> interface.
>> 
>> Current map implementation by design doesn't know anything about range 
>> it processes. If we try to define Promise monad as a range it will 
>> practically be useless unless we provide a custom map implementation 
>> for promises, because std.algorithm.map will return a wrapper range 
>> that will call popFront() that will block and wait for the value but 
>> that defeats the purpose entirely as we wanted the result to be mapped 
>> asynchronously when it will be available and not block.
>> What about other monads? Defining IO or State monads as a range would 
>> be just impossible
>> 
>> So input range can be viewed as a monad but not the other way around.
>> 
>> Each monad needs its own unique flatMap implementation
> 
> But then, these other monads could be defined in D using UFCS?  Or is D 
> syntax not generic enough to define monads?

Yes, they could be defined with or without UFCS, it may just be a 
little inconvinient to use without syntax sugar. Monads could be 
defined in any language that has first class functions



More information about the Digitalmars-d-learn mailing list