Monads compared to InputRanges?
Shammah Chancellor
anonymous at coward.com
Tue Dec 3 15:02:13 PST 2013
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?
More information about the Digitalmars-d-learn
mailing list