Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting rid of the "pyramid of doom" in F#

Tags:

f#

I have several verbal expressions that I've packaged into one function:

open FsVerbalExpressions
open FsVerbalExpressions.VerbalExpression
open System.Text.RegularExpressions
open System

let createOrVerbExFromList (verbExList: VerbEx list) = 
    let orVerbEx = 
        verbExList
        |> List.reduce (fun acc thing -> verbExOrVerbEx RegexOptions.IgnoreCase acc thing) //simpleVerbEx

    orVerbEx 

let k12VerbEx =     
    let kTo12 =  ["SCHOOL"; "DIST"; "SD"; "HS"; "BD OF ED"]
    kTo12
    |> List.map (fun word -> VerbEx(word))
    |> createOrVerbExFromList

let twoYearCollegeVerbEx = 
    VerbEx("2 Year College")

let universityVerbEx = 
    VerbEx("UNIV")

let privateSchoolVerbEx = 
    VerbEx("ACAD")

//Here there be dragons:
let newInst (x: string) =
    match (isMatch x k12VerbEx) with 
    | true -> "K - 12"
    | _ -> match (isMatch x twoYearCollegeVerbEx) with
            | true -> "2 Year College"
            | _ -> match (isMatch x universityVerbEx) with
                    | true -> "University" 
                    | _ -> match (isMatch x privateSchoolVerbEx) with
                            | true -> "Private / Charter School"
                            | _ -> "Other"

I'd like to rewrite the newInst function so that it's no longer the "pyramid of doom. My question is how can I get rid of the pyramid of doom? Can I get rid of it? I have the suspicion that it will be some sort of async workflow or other computational expression, but those are all very new to me.

like image 873
Steven Avatar asked Oct 04 '16 17:10

Steven


1 Answers

If you are only matching against booleans, then if ... elif is sufficient:

let newInst (x: string) =
    if isMatch x k12VerbEx then
        "K - 12"
    elif isMatch x twoYearCollegeVerbEx then
        "2 Year College"
    elif isMatch x universityVerbEx then
        "University"
    elif isMatch x privateSchoolVerbEx then
        "Private / Charter School"
    else
        "Other"

A more flexible possibility would be to create an active pattern:

let (|IsMatch|_|) f x =
    if isMatch x f then Some () else None

let newInst (x: string) =
    match x with
    | IsMatch k12VerbEx -> "K - 12"
    | IsMatch twoYearCollegeVerbEx -> "2 Year College"
    | IsMatch universityVerbEx -> "University"
    | IsMatch privateSchoolVerbEx -> "Private / Charter School"
    | _ -> "Other"
like image 106
Tarmil Avatar answered Sep 27 '22 23:09

Tarmil