14 Replies - 884 Views - Last Post: 03 May 2013 - 08:16 AM

#1 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5796
  • View blog
  • Posts: 12,631
  • Joined: 16-October 07

F# Option, does map_default exist?

Posted 29 April 2013 - 01:14 PM

Been playing around with F# for a week now. It's rather amusing and I love having a .NET REPL; kind of what I wanted PowerShell to be.

So, Options. It's a standard Nullable wrapper that goes all the way back to ML.

Usage looks like:
let exists (x : int option) = 
    match x with
    | Some(x) -> true
    | None -> false



While matching is nice, sometimes I just need a Some x or y kind of thing. I ended up writing this, which works fine:
// returns d if o is None
let dov<'a> (d:'a) (o:'a option) = match o with | Some x->x | None->d

// e.g.
[ Some 4; None; Some 12] |> List.map (dov 42)
val it : int list = [4; 42; 12]



While the default value in front is a little awkward, the currying for things like the above example seems worth it.

Note, ocaml's function, similar to this, is map_default.

The question is, am I missing something? Is there some simple built in way to do this? Or is this somehow considered bad form?

Is This A Good Question/Topic? 0
  • +

Replies To: F# Option, does map_default exist?

#2 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2251
  • View blog
  • Posts: 9,435
  • Joined: 29-May 08

Re: F# Option, does map_default exist?

Posted 29 April 2013 - 01:39 PM

baavgai Are you Google Fu-cked out?

Spoiler

Was This Post Helpful? 0
  • +
  • -

#3 cfoley  Icon User is offline

  • Cabbage
  • member icon

Reputation: 1948
  • View blog
  • Posts: 4,048
  • Joined: 11-December 07

Re: F# Option, does map_default exist?

Posted 29 April 2013 - 03:06 PM

How does that work when you want to change the default? In Baavgai's example, a sensible default for adding all the Options in the list is zero. The default for multiplication would be one.

This post has been edited by cfoley: 29 April 2013 - 03:07 PM

Was This Post Helpful? 0
  • +
  • -

#4 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5796
  • View blog
  • Posts: 12,631
  • Joined: 16-October 07

Re: F# Option, does map_default exist?

Posted 30 April 2013 - 04:00 AM

@AdamSpeight2008: No, using the default of a type isn't the point. Indeed, I'm not sure where I'd much care for that, since the default of any .NET class type would be null, which is wrong in so many ways.

Curiously, most of F#'s types are implemented as classes, so you'll get this:
type Foo = { Value: int }
Unchecked.defaultof<Foo>
// val it : Foo = null



In any case, offering an alternate implementation to mine, even if not apropos, isn't the point. The question is, shouldn't there already be a standard way to do this?

By way of example, the ocaml function I referenced is trivial to implement:
let map_default<'a,'b> (f: 'a -> 'b ) (b:'b )  (a:'a option): 'b =
  match a with 
    | Some x->f x 
    | None->b



Would be used like:
[ Some 'a'; Some 'b'; None] |> List.map (map_default System.Char.ToUpper 'X')
val it : char list = ['A'; 'B'; 'X']



Here, the intent is slightly different, providing a fallback for a transformation and a potential type change.

The function I'm talking about could be written, given map_default, as:
let dov<'a> (d:'a) (o:'a option) = map_default (fun x->x)


This post has been edited by baavgai: 30 April 2013 - 04:02 AM

Was This Post Helpful? 0
  • +
  • -

#5 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2251
  • View blog
  • Posts: 9,435
  • Joined: 29-May 08

Re: F# Option, does map_default exist?

Posted 30 April 2013 - 09:47 AM

Is Options.Map? what you're looking for?
Was This Post Helpful? 0
  • +
  • -

#6 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5796
  • View blog
  • Posts: 12,631
  • Joined: 16-October 07

Re: F# Option, does map_default exist?

Posted 30 April 2013 - 12:16 PM

Nope, but thanks.

The Option functions are interesting. Many essentially exist to apply functions to an option value while maintaining the option wrapper.

e.g. for map:
map : ('T -> 'U) -> 'T option -> 'U option



Meaning it takes a transformation function for the value type. It then takes an option type of 'T in and spits out an option type of 'U out.

It's for operations where you want to just dodge the None.

e.g.
[1; 2; 3; 4] |> List.map (fun x->x*x)
> val it : int list = [1; 4; 9; 16]

[Some 1; Some 2; None; Some 4] |> List.map (fun x->x*x)
> The type 'int option' does not support the operator '*'



Of course, the second one doesn't work.

To work around the Option, you need something like:
[Some 1; Some 2; None; Some 4] |> List.map (fun ox->match ox with | Some x -> Some(x*x) | None->ox)
> val it : int option list = [Some 1; Some 4; null; Some 16]



Messy, but doable.

The Option map let you clean that up:
[Some 1; Some 2; None; Some 4] |> List.map (Option.map (fun x->x*x))
> val it : int option list = [Some 1; Some 4; null; Some 16]


Was This Post Helpful? 0
  • +
  • -

#7 cfoley  Icon User is offline

  • Cabbage
  • member icon

Reputation: 1948
  • View blog
  • Posts: 4,048
  • Joined: 11-December 07

Re: F# Option, does map_default exist?

Posted 30 April 2013 - 02:23 PM

It does seem like a glaring omission. Even Java's upcoming Optional type has the orElse() method
http://download.java....html#orElse(T)

Is F#'s Option a class? If you can create a subclass, that could be a partial solution (although I think your dov function is nicer.)
Was This Post Helpful? 0
  • +
  • -

#8 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1622
  • View blog
  • Posts: 5,709
  • Joined: 03-August 09

Re: F# Option, does map_default exist?

Posted 30 April 2013 - 02:24 PM

I really like this but I can't say it's a glaring omission, at least not from my experience with Haskell.

View Postbaavgai, on 30 April 2013 - 08:16 PM, said:

The Option functions are interesting. Many essentially exist to apply functions to an option value while maintaining the option wrapper.


Haskell programmer: *cough* Monad *cough*

;)

This post has been edited by ishkabible: 30 April 2013 - 02:28 PM

Was This Post Helpful? 0
  • +
  • -

#9 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5796
  • View blog
  • Posts: 12,631
  • Joined: 16-October 07

Re: F# Option, does map_default exist?

Posted 30 April 2013 - 05:45 PM

View Postishkabible, on 30 April 2013 - 05:24 PM, said:

Haskell programmer: *cough* Monad *cough*


Well, yes. :P The whole pipe thingy IS a monad. But I like F#'s syntax better than haskell.

View Postcfoley, on 30 April 2013 - 05:23 PM, said:

Java's upcoming Optional type has the orElse() method
...
Is F#'s Option a class? If you can create a subclass


I can do better than a subclass:
type Option<'T> with
  member this.orElse(other: 'T) =
    match this with | Some x->x | None->other

let a = Some(2)
let b = None

printfn "%A %A" (a.orElse(3)) (b.orElse(3))



The thing is, I'm not convinced it's a good solution. For an OO programmer, sure. But as a simple functional solution... There's a design aesthetic to having the types lean and mean and providing support functions for them.

Compare the solution I originally offered with the member function option.
[ Some 4; None; Some 12] |> List.map (dov 42)

[ Some 4; None; Some 12] |> List.map (fun x->x.orElse(42))



There are also other tricks that can be done by having simple little functions. e.g.
let square x = x * x
let opSq = dov 0 >> square

[ Some 4; None; Some 12] |> List.map opSq



This is really the point of the question. I'm not an experienced functional programmer, but I'm learning. As a long time OO programmer, my defaults could be counter to the paradigm I'm trying to grok. So, looking for a more experienced functional programming perspective.
Was This Post Helpful? 1
  • +
  • -

#10 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1622
  • View blog
  • Posts: 5,709
  • Joined: 03-August 09

Re: F# Option, does map_default exist?

Posted 01 May 2013 - 11:52 AM

Quote

Well, yes. The whole pipe thingy IS a monad. But I like F#'s syntax better than haskell.


I haven't used F# enough to say weather I like it more or not but from what I've seen it seems a bit verbose compared to Haskell. What is it that you like better? Not that this really matters I'm just curious.
Was This Post Helpful? 0
  • +
  • -

#11 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5796
  • View blog
  • Posts: 12,631
  • Joined: 16-October 07

Re: F# Option, does map_default exist?

Posted 02 May 2013 - 02:23 AM

To be fair, I've NEVER played with Haskell, so I can't seriously comment. So, being uninitiated, most Haskell code snippets look to me like symbol soup.

However, before I started playing with F#, some of the work flows were immediately apparent. While I didn't know what things like "|>" were actually doing, I could infer the meaning. F# has it's share of symbol overload, but it's mitigated with things like required white space and some, I guess, extra verbosity. Of course, compared to C#, F# syntax is practically parsimonious.

Ultimately, unlike other functional languages I've played with, F# is something I can use at work. Sitting in .NET, it's less an academic diversion and more a new tool in the daily tool box.
Was This Post Helpful? 0
  • +
  • -

#12 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2251
  • View blog
  • Posts: 9,435
  • Joined: 29-May 08

Re: F# Option, does map_default exist?

Posted 02 May 2013 - 04:53 AM

|> is really close to how extension methods work. (Not quite but close).

Take the result pass it as the first argument of the function.

|> (param1 ) {Function Name} {rest of params}
Was This Post Helpful? 0
  • +
  • -

#13 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5796
  • View blog
  • Posts: 12,631
  • Joined: 16-October 07

Re: F# Option, does map_default exist?

Posted 02 May 2013 - 11:40 AM

In F#, all functions are curried. Indeed, the functions that look like they're not are actually just getting passed tuples.

In effect f x y z is called as (((f x) y) z). The result of f x being return first and so on.

We can confirm this:
> let sum x y z = x + y + z
let s1 = sum 2
let s2 = s1 3
;;

val sum : x:int -> y:int -> z:int -> int
val s1 : (int -> int -> int)
val s2 : (int -> int)


> s2 10;;

val it : int = 15



Cool, huh?

You can call our sum x y z with the following forms:
sum 1 2 3
(sum 1 2) 3
3 |> sum 1 2
sum 1 2 <| 3



When you really grok this, it all makes a lot more sense.
Was This Post Helpful? 0
  • +
  • -

#14 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5796
  • View blog
  • Posts: 12,631
  • Joined: 16-October 07

Re: F# Option, does map_default exist?

Posted 02 May 2013 - 07:03 PM

Found it: defaultArg

e.g.
defaultArg (Some 4) 12
defaultArg None 12


Was This Post Helpful? 3
  • +
  • -

#15 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1622
  • View blog
  • Posts: 5,709
  • Joined: 03-August 09

Re: F# Option, does map_default exist?

Posted 03 May 2013 - 08:16 AM

View Postbaavgai, on 02 May 2013 - 10:23 AM, said:

...
So, being uninitiated, most Haskell code snippets look to me like symbol soup.
...
While I didn't know what things like "|>" were actually doing, I could infer the meaning.
...


Ya, when I first looked at Haskell my impression was that it was symbol soup. I was as discouraged by Haskells's syntax as I was by lisp's when I first saw it. After I learned it however, I got to where I could infer the meaning of new operators as well. Granted, I still have to look quite a bit up when looking at a new library.

Quote

Ultimately, unlike other functional languages I've played with, F# is something I can use at work. Sitting in .NET, it's less an academic diversion and more a new tool in the daily tool box.


I'm actually going to be working on a project this summer in Haskell! I never actually thought I would get to use it.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1