Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructing a record with a power of Applicative in F#

Tags:

haskell

f#

Suppose there is a type r = {A : int; B : string; C : int; D : string} and a some values:

let aOptional : int option = ...
let bOptional : string option = ...
let cOptional : int option = ...
let dOptional : string option = ...

How can r optional could be constructed from them eleganlty (without nested case-stuff, etc.)?


Btw, here is how it could be done in haskell with Control.Applicative:

data R = R { a :: Integer, b :: String, c :: Integer, d :: String}

R <$> aOptional <*> bOptional <*> cOptional <*> dOptional :: Maybe R

Looking for something equivalent in fsharp.

like image 942
ДМИТРИЙ МАЛИКОВ Avatar asked Dec 05 '25 20:12

ДМИТРИЙ МАЛИКОВ


2 Answers

The only way I know (using applicatives) is by creating a function to construct the record:

let r a b c d = {A = a; B = b; C = c; D = d}

Then you can do:

> r </map/> aOptional <*> bOptional <*> cOptional <*> dOptional ;;

val it : R option

You can define map and <*> yourself, but if you want a generic implementation try that code with F#+ or if you want to use FsControl directly you can write the code this way:

#r "FsControl.Core.dll"

open FsControl.Operators

let (</) = (|>)
let (/>) f x y = f y x

// Sample code
type R = {A : int; B : string; C : int; D : string}
let r a b c d = {A = a; B = b; C = c; D = d}

let aOptional = Some 0
let bOptional = Some ""
let cOptional = Some 1
let dOptional = Some "some string"

r </map/> aOptional <*> bOptional <*> cOptional <*> dOptional
// val it : R option = Some {A = 0; B = ""; C = 1; D = "some string";}

UPDATE: Nuget packages are available now.

like image 158
Gus Avatar answered Dec 08 '25 21:12

Gus


The straightforward way is:

match aOptional, bOptional, cOptional, dOptional with
| Some a, Some b, Some c, Some d -> Some {A=a; B=b; C=c; D=d}
| _ -> None

or, with a maybe monad:

let rOptional = 
  maybe {
    let! a = aOptional
    let! b = bOptional
    let! c = cOptional
    let! d = dOptional
    return {A=a; B=b; C=c; D=d}
  }
like image 30
Daniel Avatar answered Dec 08 '25 23:12

Daniel