-1

I need to extract a string version of state from a record. Code below:

type State = State of string

type Data = 
   { State : State
     Year : int
     Income : float }

What I need to do is extract a sequence of the string version of each state, and not State "string". When I try to do something like below, I get an empty sequence. I run the code below after running code which processes and maps data to the above records.

let states (row:Data) = row.State
// <fun:it@145-1> val it : unit = ()

I need a sequence because in the end I will use this to check and make sure the states in one dataset are in a sequence of another.

EDITED:

After doing something like what is below, I still get the empty sequence.

let stateToStr (State s) = s
let statec (row:StateCsv) = (stateToStr row.State)
printfn "%A" statec
// val stateToStr : State -> string
// val statec : row:StateCsv -> string
// val it : unit = ()

Again after maping data to records like so:

let statepa () =
  Stat.GetSample().Rows
  |> Seq.map(fun row ->  
    { State = row.STATE 
      Year  = row.Year })
SantiClaus
  • 666
  • 2
  • 8
  • 22
  • When you say "I get an empty sequence", do you mean the `()` in the output that you're showing? Because `()` is *not* an empty sequence. `()` is a special value called "unit", which is what is returned by functions that don't have any meaningful return value (like `printfn`, which only prints things to the screen and doesn't return anything). Read more about it [here](https://stackoverflow.com/a/33949801/2314532) or [here](https://stackoverflow.com/a/50616001/2314532) (note that that first link is to a question about Elm, but F#'s `unit` is the same thing as Elm's `unit`). – rmunn Jun 17 '18 at 11:08
  • Also, when you do `printfn "%A" statec`, what do you expect that to do? Because what it will *actually* do is print *the function itself*, which is rarely useful. What I think you meant to do is something `printfn "%A" (statec someRow)`, which would have passed a row of data to the function as input, and printed the *result* of the function. – rmunn Jun 17 '18 at 11:09

1 Answers1

3

In general, you can "unwrap" a single-case discriminated union (like your State type) with pattern matching:

let ma = State "MA"
let (State str) = ma
printfn "%s" str   // prints "MA"

Or, you can put the pattern in a function's argument:

let stateToStr (State s) = s
printfn "%s" (stateToStr ma)   // prints "MA"

Or, if you only need to do this once in your states function, you can nest the State pattern right within the Data pattern:

let states { State = State s } = s

let row = { State = State "MA"; Year = 1; Income = 2. }
printfn "%s" (states row)   // Prints "MA"

Patterns can be nested, that's their great power.
This particular one consists of two nested patterns: pattern { State = x } binds x to the value of field State of the incoming record, and pattern State s binds s to the "inner value" of State.

Fyodor Soikin
  • 78,590
  • 9
  • 125
  • 172
  • 2
    I can't really say anything about that, because I have no idea what `StateCsv` is. Also, why are you trying to print a function? – Fyodor Soikin Jun 17 '18 at 04:00
  • 3
    Then asks that as a separate question, @FyodorSoikin already answers the current question which was about "Dealing with records". –  Jun 17 '18 at 06:59