SuperCell
SuperCell

Reputation: 241

Incomplete pattern matching in F# using read files and lists

So i have this code

let readLines filePath = System.IO.File.ReadLines(filePath);
let lines = Seq.toList (readLines "MovieSmall.txt");
let lines2 = List.map (fun (s:string) -> Array.toList (s.Split([|'\t'|]))) lines;
let imdb = List.map (fun (l1::l2::l3::l4::l5::l6::[]) -> [l1]::[l2]::[l3]:: (Array.toList ((l4:string).Split[|','|])) ::[l5]:: (Array.toList ((l6:string).Split[|','|])) ::[]) lines2;;

That gets data from a file called MovieSmall and parses it into a String Linked List.

MovieSmall.txt looks like this

The Shawshank Redemption    1994    9.30    Crime, Drama     Frank Darabont  Morgan Freeman
The Godfather   1972    9.20    Crime, Drama     Francis Ford Coppola    Al Pacino,  James Caan,  Robert Duvall,  Diane Keaton,  Talia Shire
Universal's Cinematic Spectacular: 100 Years of Movie Memories  2012    9.20    Documentary, Short   Mike Aiello     Morgan Freeman

I get

  let imdb = List.map (fun (l1::l2::l3::l4::l5::l6::[]) -> [l1]::[l2]::[l3]:: (Array.toList ((l4:string).Split[|','|])) ::[l5]:: (Array.toList ((l6:string).Split[|','|])) ::[]) lines2;;
  --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^

stdin(4,27): warning FS0025: Incomplete pattern matches on this expression. For example, the value '[_;_;_;_;_;_;_]' may indicate a case not covered by the pattern(s).

Which I'm sure is ok because all the data fed to it will have the format above, but when I run

let rec get_rating movie = function
    | [] -> "Not found";
    | [[title]; b; c; d; e; f]::t -> if title=movie then  (string)c else get_rating movie t;

get_rating "Batman Begins" imdb;;

i get

let rec get_rating movie = function
  ---------------------------^^^^^^^^

stdin(24,28): warning FS0025: Incomplete pattern matches on this expression. For example, the value '[[_;_;_;_;_;_;_]]' may indicate a case not covered by the pattern(s).

val get_rating :
  movie:'a -> _arg1:'a list list list -> string when 'a : equality
val it : string = "[8.30]"

While adding the case of

let rec get_rating movie = function
    | [] -> "Not found";
    | [[title]; b; c; d; e; f]::t -> if title=movie then  (string)c else get_rating movie t;
    |_-> "Does not match";

get_rating "Batman Begins" imdb;

Stops it from happening I dunno if this is the correct way to approach this. Thoughts?

Upvotes: 0

Views: 292

Answers (2)

s952163
s952163

Reputation: 6324

You can disable compiler warnings:

#nowarn "25"

Upvotes: -1

egerhard
egerhard

Reputation: 1109

When you only want to match on a small subset of all the possible patterns, as you're doing here, then finishing the match statement with _ -> default logic is exactly what you want to do.

The F# compiler is throwing that warning because when you leave your pattern matches incomplete you're opening your code up to run time failures when unexpected data comes through. Added the | _ -> pattern at the end lets you dictate what action to take when something unexpected happens.

Long story short, you're taking the right approach by having the _-> "Does not match" in your code.

Upvotes: 4

Related Questions