4 Replies - 1252 Views - Last Post: 14 August 2015 - 04:40 AM

#1 BLincolnGreen  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 8
  • Joined: 13-August 15

Functional Programming: Monads have state? Scala Option

Posted 13 August 2015 - 02:26 PM

In functional programming it seems that state is stored in Monads. Does it follow then that code that employs Monads does not get the concurrency benefits that non-Monad code would have?

I was watching a video that was based on Scala and there was significant usage of the Option monad. Is this code still able to be processed in a concurrent fashion? If so, how?

Disclaimer: I have never programmed a line of code in a functional language although I have used similar concepts in OO languages. So I might have this totally wrong.

Is This A Good Question/Topic? 0
  • +

Replies To: Functional Programming: Monads have state? Scala Option

#2 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: Functional Programming: Monads have state? Scala Option

Posted 13 August 2015 - 03:11 PM

Monads can be used to encapsulate state (as is the case with the IO, State and St monads in Haskell for example), but that's not the purpose of every monad.

Note that mutable state can already be used in Scala (as well as most languages that aren't Haskell) easily without the use of any methods, so there's less need for state-encapsulating monads.

The purpose of the Option monad is to easily and safely represent a chain of operations that may not produce a result. As an example compare the following two functions:

// Version without Option

String f();
// Assume that these two functions throw a NullPointerException when called with a null argument
String g(String s);
String h(String s);

// The intended result is h(g(f())), except we want to handle the possibility of any of the functions returning null
String foo() {
  String s1 = f();
  if(s1 == null) return null;
  String s2 = g(s1);
  if(s2 == null) return null;
  return h(s2);
}


// Version with Option
Option<String> f();
// Assume that these two functions throw a NullPointerException when called with a null argument
Option<String> g(String s);
Option<String> h(String s);

Option<String> foo() =
    for(s1 <- f(); s2 <- g(s1); s3 <- h(s2))
        yield s3;



Why did I write this in this weird mix of Java and Scala syntax? No particular reason - it just kinda turned out that way and now I'm too lazy to change it.

Note that if you forgot any of the nullchecks in the first version, this would lead to possible runtime exceptions without any warning (or error) from the compiler. Also the code isn't particularly pretty.

In the second version, you can't forget any "None checks" as these checks are implicit through the semantics of the monad.

The same benefit could be achieved without making use of the fact that Option is a monad (i.e. without Scala's "Why does this look like a for-loop? This is not a for-loop!"-syntax) by using Option's methods and maybe it would be more readable that way, but you asked about it in the context of monads, so that's why I used this syntax.
Was This Post Helpful? 0
  • +
  • -

#3 BLincolnGreen  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 8
  • Joined: 13-August 15

Re: Functional Programming: Monads have state? Scala Option

Posted 13 August 2015 - 04:30 PM

// Assume that these two functions throw a NullPointerException when called with a null argument
Option<String> g(String s);
Option<String> h(String s);

Option<String> foo() =
for(s1 <- f(); s2 <- g(s1); s3 <- h(s2))
yield s3;
[/code]


Thanks for the explanation. The syntax is fine. So from the presentation I got the idea that Option in particular had state. In this code
Option.Some contains the yielded value if I followed the explanation in the video. And there are potentially many Option instances used in the flatmap. So is this code with stateful option still able to be processed concurrently?
Was This Post Helpful? 0
  • +
  • -

#4 BLincolnGreen  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 8
  • Joined: 13-August 15

Re: Functional Programming: Monads have state? Scala Option

Posted 13 August 2015 - 04:45 PM

Also in the video the example given was in terms of lists. And
for...yield
seemed to amount to what
main()
does below. Is there a way to omit nulls instead of exiting as soon as one is found?

Function iLikeIceCream(flavor as IceCream) Returns Boolean
   /* assuming that the args cant be null since this is evidently true in Scala
     so no null checks on arguments
  */
   if (flavor.Name == "Chocolate") {return Boolean.FALSE;}
   if (flavor.Name == "Vanilla") {return Boolean.TRUE;}
   if (flavor.Name == "Butter Pecan") {return Boolean.TRUE;}
   return null;
End-Function;

Function iLikePie(flavor as Pie) Returns Boolean
   /* assuming that the args cant be null since this is evidently true in Scala
     so no null checks on arguments
  */
   if (flavor.Name == "Pear") {return Boolean.FALSE;}
   if (flavor.Name == "Watermelon") {return Boolean.FALSE;}
   if (flavor.Name == "Canteloupe") {return Boolean.FALSE;}
   if (flavor.Name == "Apple") {return Boolean.TRUE;}
   if (flavor.Name == "Chocolate Cream") {return Boolean.TRUE;}
   if (flavor.Name == "Pumpkin") {return Boolean.TRUE;}
   return null;
End-Function;

List<alaMode> Function getDesserts(pies as List<Pie>, iceCreams as List<IceCream>, pieChooser as PieSelector, iceCreamChooser as IceCreamSelector)
   /* assuming that the args cant be null since this is evidently true in Scala
     so no null checks on arguments
  */
  List<alaMode> myList = new List();
  for (int i=0; i < pies.size; i++) {
     Pie myPie = pies.get(i);
     Boolean goodPie = pieChooser(myPie);
     if (goodPie == null) {return null;}     /* we're outta here as soon as something is null */
     if (goodPie == Boolean.FALSE) {continue;}
     for (int j=0; j < iceCreams.size; j++) {
        IceCream myIceCream = iceCreams.get(j);
        Boolean goodIceCream = iceCreamChooser(myIceCream);
        if (goodIceCream == null) {return null;}      /* we're outta here as soon as something is null */
        if (goodIceCream == Boolean.FALSE) {continue;}
        alaMode dessert = new alaMode(myPie, myIceCream);
        myList.add(dessert);
     }
  }
End-Function;

Option<List> Function wrapInOption((func as FunctionCall))
   /* assuming that the args cant be null since this is evidently true in Scala
     so no null checks on arguments
  */
   List result = func.execute();
   Option myOption = new Option();
   if (result != null) {
      myOption.Some = result;
   }
   return myOption;
End-Function;

void Function main()
   List<Pie> myListOfPies = new List();
   myListOfPies.populateByMagic();
   List<IceCream> myListOfIceCreams = new List();
   myListOfIceCreams.populateByMagic();
   pieChooser myPieChooser = iLikePie;
   iceCreamChooser myIceCreamChooser = iLikeIceCream;
   Option myOption = wrapInOption(new functionCall(getDesserts(myListOfPies, myListOfIceCreams, myPieChooser, myIceCreamChooser)));
End-Function;


Was This Post Helpful? 0
  • +
  • -

#5 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon


Reputation: 6995
  • View blog
  • Posts: 14,630
  • Joined: 16-October 07

Re: Functional Programming: Monads have state? Scala Option

Posted 14 August 2015 - 04:40 AM

My daily FP language is F#. I use Option all the time. In Haskell and the MLs, you have a whole lot of interesting types. An Option is simply a type that has two possible values, None or Some x where x is the value. Essentially, Option is Nullable for languages that don't have null.

Curiously, even in languages where objects can be null, primitives often can't be. In this case, a wrapper class called something like Nullable ( C# ) is often used. On the flip side, simply returning a null often breaks things if the programmer doesn't check. In which case, using the wrapper forces the programmer to check.

Using Option forces the programmer to always deal with the possibility of None. While this can be annoying, it's less so than being burnt by a future null.

Quick F# code dump:
 
// make an int list
let xs = [ 1..10 ]
> val xs : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]

// I want to be able to find any value in that list
// So, finder function
let finder n = List.tryFind (fun x->x=n) xs
> val finder : n:int -> int option

// Basically, List.tryFind returns an option and we have to deal with it.
// The alternative, List.try, throws an exception which just sucks
// Better to have a value type that can indicate you failed or give a value

// Let's test
finder 3
> val it : int option = Some 3

finder 30
> val it : int option = None

// cool.  Now, let's look for values in a list
let ys = [ 3; 5; 8; 13 ] |> List.map finder
> val ys : int option list = [Some 3; Some 5; Some 8; null]

// Well, that's good, but we really wanted an int list, not an int option list
// Perhaps we can filter the None out 
// (Note, F# calls None null here)
ys |> List.filter Option.isSome
> val it : int option list = [Some 3; Some 5; Some 8]

// We got rid of out None, but not the option
ys |> List.filter Option.isSome |> List.map Option.get
> val it : int list = [3; 5; 8]
// bingo!



Note the pipe thingy (|>) is an F#ism that essentially translates x |> f to f x. Which means that last line can be written List.map Option.get (List.filter Option.isSome ys). It's the difference of reading from inside parens to outside or left to right. Once you find a way to mitigate paren clutter in FP, it's hard to go back. (e.g. Haskell's $) The Lisps give me dyslexic fits.

Hope this helps.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1