Specifying a generic parameter in a double list in F# - f#

I am creating a function in F# which is given a list of lists, and which returns true, if all lists are of the same length, except if this length is 0.
I want to specify that the entries of the inner list can be a generic type 'T, so I was going for
let properTable (input : list list<'T>) : bool =
let lengths = set ([for i in 0..(input.Length-1) -> input.[i].Length])
not (lengths.Contains(0)) && lengths.Count = 1
When pasting this function into F# interactive, I get the error message:
stdin(148,35): error FS0010: Unexpected type application in pattern. Expected ')' or other token.
If I replace the type the type of input with int list list, the function works, but I'd like any type, not just an int.
I can get it to work with only a single list, as in
let testSingleList (input : list<'T>) : bool =
input.Length > 0
How can I accomplish a similar construction, but for a list of lists?

You're mixing two different "styles" of type annotation.
Using either
'T list list
or
List<List<'T>>
should work.

Related

F# list of discriminated union sub-types

I want to present the user with a list of 'FParsec parsers'-plus-'test data' from which they can interactively select and see the results of the parser run on the supplied text.
Specifically, am trying to collect my parser tests in a list of records of this type:
type FUNCTION_TEST =
| XELEMENT_MATCH of label : string * func : Parser<(int * string), unit> * data : string
| XKEYVALUE_MATCH of label : string * func : Parser<(string * string), unit> * data : string
let testable_parsers = [( "xElement", xElement, xElement_text3)
( "xKeyValue", xKeyValue, xKeyValue_text)]
xKeyValue above throws the error...
val xKeyValue: Parser<(string * string), unit>
Full name CustomParser.xKeyValue
FS0001:the type '(int * string)' does not match the type 'string * string'
I want the user to see and choose a label string and see the results of running the parser.
I understand that the parser xElement : Parser<int * string, unit> does not match parser xKeyValue : Parser<(string * string), unit>. Both sub-types are part of the FUNCTION_TEST discriminated union BUT I cannot put the parsers in the same list because their sub-types (XELEMENT_MATCH versus XKEYVALUE_MATCH) disagree.
I wanted to handle this using a match ... with over the discriminated union.
I am new to F# and FParsec and out of elegant ideas. Do I have to hard-code a menu with do! and printfs?
How do experienced F# and FParsec developers allow users to select from a menu of options of different types?
I think the best approach would be to restructure your data so that you keep all the common things (label and data) in a record, together with a value representing the function - which can then be a discriminated union with a case for each type:
type Function =
| Element of Parser<(int * string), unit>
| KeyValue of Parser<(string * string), unit>
type Test =
{ Label : string
Data : string
Function : Function }
Now you can create a list of Test values, which you can easily iterate over to get all the labels & data:
let testableParsers =
[ { Label = "xElement"; Function = Element(xElement); Data = xElement_text3 }
{ Label = "xKeyValue"; Function = KeyValue(xKeyValue); Datta = xKeyValue_text } ]
You will still need to use pattern matching when you want to run a specific Function, because this will have to handle the different values you get as a result, but you won't need pattern matching elsewhere.
I'm a bit confounded by the FUNCTION_TEST type. It looks like you're never using the type or any of its constructors, and if so, why did you define that type in the first place?
After pondering the possible motives you may have had, it looks like perhaps you wanted the testable_parsers list to contain values of the FUNCTION_TEST type so that you can later match on them?
If that is the case, then what you have is not what you intended: the list that you have constructed contains tuples of three values.
In order to construct values of the FUNCTION_TEST type, you need to apply its constructors:
testableParsers = [
XELEMENT_MATCH ("xElement", xElement, xElement_text3)
XKEYVALUE_MATCH ("xKeyValue", xKeyValue, xKeyValue_text)
]
But if your only purpose is to present a choice to the user, then I wouldn't even bother with a special type to represent the options. You can just pair labels with functions to be called when the user chooses the label:
testableParsers = [
"xElement", fun() -> runParser xElement xElement_text3
"xKeyValue", fun() -> runParser xKeyValue xKeyValue_text
]
This way you don't have to do a match on the values of FUNCTION_TEST either, just call the function.

Splitting a list at given index f#

For a class I'm following, I have to do the following exercise:
Implement a function
let splitAt (i : int) (l : List<'a>) : List<'a> * List<'a> = ...
that splits the list into two lists, the rst one containing all the elements of l from position 0 to position i
included, and the second one containing all the remaining elements. The two resulting lists are returned
in a tuple. For example:
split 3 [3;5;4;-1;2;2] = ([3;5;4;-1],[2;2])
We have to do these problems only using functional programming, and thus I'm not allowed to use pre-existing functions.
I have the following code which seems to me to (logically) be correct:
let splitAt (i:int)(l: List<'a>): List<'a> * List<'a> =
let rec loop n startlist restlist =
if n = i then
restlist * startlist
else
match startlist with
| h :: t -> loop (n+1) [t] [(restlist :: h)]
| h :: [] -> None
loop 0 l []
and below my [<EntryPoint>]
printfn "%A" (splitAt stringlist 3)
However, this gives me a couple of errors, namely:
None of the types 'a list, 'a list support the operator *
This expression was expected to have type int but here has type char list
This expression was expected to have type List<'a> but here has type int
The * operator is used for declaring a tuple type, but when you're building a tuple you use , instead. So you want restlist, startlist.
Then you'll discover that there's another type error, because one branch of your match expression returns None. That's an option type, so the value you return should be a Some. So you want Some (restlist, startlist).
And now you'll discover one more type error, which is that you've declared that the function returns a tuple but in fact it returns a tuple option (that is, either None or Some tuple). So your type declaration needs to become (List<'a> * List<'a>) option.
For more on why * is used in declaring tuple types rather than ,, https://fsharpforfunandprofit.com/posts/tuples/ is a good read.

Currying issues with F#. What is the right way to attach functions to the type?

I can't understand what is wrong with following bit of code:
let toClass (problem:Problem<'a>) (classID:int) (items:'a list) =
let newFreqTable = (problem.FreqTables.[classID]).count items
{ problem with FreqTables = newFreqTable :: (problem.FreqTables |> List.filter (fun i -> i.ClassID <> classID)) }
type Problem<'a> when 'a : equality with member this.toClass (classID:int) (items:list<'a>) = toClass this classID items
I have a Problem type which is nothing but a way to group up any number of FreqTables - short for "Frequency tables". So toClass method just takes appropriate freqTable (by classID argument) and returns a new one - with calculated given items.
let typeIndependentCall = toClass p 0 ["word"; "word"; "s"] // this works perfectly
let typeDependentCall = typeIndependentCall.toClass 1 ["word"; "s"]
// gives an error: "One or more of the overloads of this method has
// curried arguments. Consider redesigning these members to take
// arguments in tupled form".
I am pretty new to F# and functional programming. What is the right way to attach behavior to my type?
In F# there are 2 main ways of passing arguments to a function: curried and tupled. The curried form is what you are using in your code above, and has a few key benefits, the first and foremost being partial application.
For example, instead of thinking of
fun add a b = a + b
as a function that takes in 2 arguments and returns a value, we can think of it as a function of one argument that returns a function that with one argument. This is why the type signature of our function is
Int -> Int -> Int
or, more clearly,
Int -> (Int -> Int)
However, when overloading methods, we can only use the tupled argument form
(Int, Int) -> Int
The reason for this is for optimization, as is discussed here
To get your code to work, use
type Problem<'a> when 'a : equality with member this.toClass (classID:int, items:list<'a>) = toClass this classID items
and call it like such:
let typeDependentCall = typeIndependentCall.toClass(1, ["word"; "s"])

Variance of function types wrt. interfaces

I'm trying to understand the variance rules for function types. It seems they don't treat input and output the same (up to duality). Consider this program.
let mk1 s = s |> Seq.iter (fun _ -> ())
// val mk1 : s:seq<'a> -> unit
let mk2 = mk1 : list<int> -> unit // Ok.
let mk3 () = [1]
// val mk3 : unit -> int list
let mk4 = mk3 : unit -> seq<int> // Type mismatch.
This is the error:
Type mismatch. Expecting a
unit -> seq<int>
but given a
unit -> int list
The type 'seq<int>' does not match the type 'int list'
It's my understanding that seq<int> is an interface type, one which int list implements, so I was expecting this cast to go through(*).
Two questions:
Why doesn't it?
Why is the cast producing mk2 ok?
(*) For theorists: I was expecting the elaborator to exhibit dual behaviour on the input and output positions of the function space type constructor. Is that wrong?
You have this:
let mk4 = mk3 : unit -> seq<int>
Which will not compile, the up-cast will happen automatically in the input parameter but never in the output of the function. This is in the spec, section 14.4.2 Implicit Insertion of Flexibility for Uses of Functions and Members.
This means that F# functions whose inferred type includes an unsealed type in argument position may be passed subtypes when called, without the need for explicit upcasts.
This makes possible to define another version of the function which is restricted to a subtype, which are the other cases you're showing.
Interestingly, you can use flexible types to define mk4 as follows:
let mk4 = mk3 : unit -> #seq<int>
It compiles but automatically lifts the type of mk4 up to unit -> int list

Seq.map from one list to populate another list of different type?

This question is in follow up to an earlier question, Preserving Field names across the F#/C# boundary
Because of the current limitation encountered with F# type providers (see the earlier question), I want to map the type-provider-generated list to my own list of records, in which the record is, in part,
type inspection = {
inspectionID : string;
inspectorID : int;
EstablishmentID : string;
EstablishmentName : string; // other members elided
}
I think the way to do this will use Seq.map, but I am not certain. (Recall I am doing a learning exercise.) So here is what I tried:
type restaurantCsv = CsvProvider<"C:\somepath\RestaurantRatings2013.csv",HasHeaders=true>
// which generates a type, but it is an "erased" type, so member names do not propogate
// over to C#.
type RawInspectionData(filename : string) =
member this.allData = restaurantCsv.Load(filename) // works fine
member this.allInspections =
this.allData.Data
|> Seq.map(fun rcrd -> new inspection[{inspectionID = rcrd.InspectionID;}])
and, of course, the complete statement would have the other member names as part of the inspection, here elided for brevity. Someone pointed me to p 43 of F# For Scientists, which is why I thought to use this format with the curly braces. But this yields a syntax error, "Unexpected symbol '{' in expression. Expected ',', ']' or other token."
Hopefully, though, this snippet is adequate to show what I would like to do, create a Generated Type from the Erased Type. How can I accomplish this?
Your code is going in the right direction. When using Seq.map (which is like Select in LINQ), you need to turn a single element of the original sequence into a single element of the new sequence. So the lambda function just needs to create a single instance of the record.
A record is constructed using { Field1 = value1; Field2 = value2; ... } so you need:
type RawInspectionData(filename : string) =
let allData = restaurantCsv.Load(filename) // works fine
member this.allInspections =
allData.Data
|> Seq.map(fun rcrd -> {inspectionID = rcrd.InspectionID})
I also changed allData from a member to a local let definition (which makes it private field of the class). I suppose that your original code new inspection[{...}] tried to create a singleton array with the element - to create an array you'd write [| { Field = value; ... } |] (and the compiler would infer the type of the array for you). But in this case, no arrays are needed.

Resources