Splitting a list at given index f# - 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.

Related

Unwrap F# single-case discriminated union tuple type

We can unwrap type like type Address = Address of string using unwrapping function like
let unwrapAddress (Address a) = a
let addr = Address "sdf"
let str = unwrapAddress addr
so str will be of type string, but if there is type like this approach willn't work:
type Composite = Composite of integer:int * someStr:string
let unwrap (Composite c) = c
will produce error
let unwrap (Composite c) = c;;
------------^^^^^^^^^^^
error FS0019: This constructor is applied to 1 argument(s) but expects 2
Can I somehow unwrap composite types to a simple tuple?
In your case, you can write:
type Composite = Composite of int * string
let unwrap (Composite (a, b)) = a, b
which corresponds to:
let unwrap x =
match x with
| Composite (a, b) -> a, b
What's happening here is that F# allows you to deconstruct function arguments inline using arbitrarily complex pattern matching. This is often mentioned when introducing single case DU's, but it's rarely followed to the conclusion, which leads people to believe single case DU's are somehow special that way.
In fact, you can use it when you have multiple cases (as long as each case binds the same set of variables):
type Composite = Composite of int * string | JustString of string
let unwrapString (Composite (_, s) | JustString s) = s
But most of the time, you'd pattern match on simpler types, like tuples:
let f (a, b, c) = ...
or even more curiously:
let f () = ...
Here () is a pattern match on the lone value of unit type - rather than some kind of "visual marker for a parameterless function", as it's often described.
You defined the type as a single-case discriminated union with named fields:
type Composite = Composite of integer:int * someStr:string
When defined in this way, the fields of the union case are not a simple tuple. They get treated in a special way and, for example, the names are used as property names in compiled code. The pattern matching does not automatically turn the elements into a tuple and so you have to unwrap them separately:
let unwrap (Composite(i, s)) = i, s
However, you can also define single-case union where the field is an ordinary tuple. (Note that you need the parentheses around the tuple type - otherwise, it also ends up being treated in a special way, except that the items will be compiled as Item1 and Item2.)
type Composite = Composite of (int * string)
With this definition, your unwrap function will work fine and extract the tuple value:
let unwrap (Composite c) = c
You can also use a nested pattern to get the number and the string like in the previous case:
let unwrap (Composite(i, s)) = i, s
The fact that this behaves differently depending on whether you write A of (T1 * T2) or whether you write A of T1 * T2 is a bit subtle - the two probably need to be distinguished just so that the compiler knows whether to compile the fields as two separate fields or as one field of type System.Tuple<T1, T2>. I cannot quite imagine any other case where the difference would matter.
These all work for me. It's your matching syntax, that most often you'll find used with match statements, but it's on the l.h.s. of an assignment. Possibly, this makes the most sense, initially, for tuples, but you can use this with any structure.
let (a,b) = (1,2)
let (x,_) = (4,5)
Two other interesting things to try:
let (head::tail) = [1;2;3;4]
FSI responds warning FS0025: Incomplete pattern matches on this expression. For example, the value '[]' may indicate a case not covered by the pattern(s).
"That's true," you reason aloud. "I should express it as a match and include an empty list as a possibility". It's better to bubble these kinds of warnings into fully bonafide errors (see: warn as error e.g. --warnaserror+:25). Don't ignore them. Resolve them through habit or the compiler enforced method. There's zero ambiguity for the single case, so code-on.
More useful + interesting is the match syntax on the l.h.s. of a function assignment. This is pretty cool. For pithy functions, you can unpack the stuff inside, and then do an operation on the internals in one step.
let f (Composite(x,y)) = sprintf "Composite(%i,%s)" x y
f (Composite(1,"one"))
> val it : string = "Composite(1,one)"
About your code:
type Address = Address of string //using unwrapping function like
let unwrapAddress (Address a) = a
let addr = Address "sdf"
let str = unwrapAddress addr
type Composite = Composite of integer:int * someStr:string
let unwrap (Composite(c,_)) = c
let cval = Composite(1,"blah")
unwrap cval
Workaround:
let xy = Composite(1,"abc") |> function (Composite(x,y))->(x,y)
... but the nicer way, assuming you want to keep the named elements of your single case DU would be...
let (|Composite|) = function | Composite(x,y)->(x,y)
let unwrap (Composite(x)) = x
let unwrap2 (Composite(x,y)) = (x,y)
... not strictly decomposing through a single case DU, but decomposing through a single-case Active Pattern
lastly, you could attach a method to the Composite structure...
module Composite =
let unwrap = function | Composite(x,y)->(x,y)
One of the best discussions about using this technique is over here
Also, check out the signature that unwrap gives us: a function that takes a Composite (in italics), and returns an int (in bold)
Signature -- val unwrap : Composite -> int

Function argument is null, even though a non-null argument is passed

F# newbie here, and sorry for the bad title, I'm not sure how else to describe it.
Very strange problem I'm having. Here's the relevant code snippet:
let calcRelTime (item :(string * string * string)) =
tSnd item
|>DateTime.Parse
|> fun x -> DateTime.Now - x
|> fun y -> (floor y.TotalMinutes).ToString()
|>makeTriple (tFst item) (tTrd item) //makeTriple switches y & z. How do I avoid having to do that?
let rec getRelativeTime f (l :(string * string * string) list) =
match l with
| [] -> f
| x :: xs -> getRelativeTime (List.append [calcRelTime x] f) xs
I step through it with Visual Studio and it clearly shows that x in getRelativeTime is a 3-tuple with a well-formed datetime string. But when I step to calcRelTime item is null. Everything ends up returning a 3-tuple that has the original datetime string, instead of one with the total minutes past. There's no other errors anywhere, until the that datetime string hits a function that expects it to be an integer string.
Any help would be appreciated! (along with any other F# style tips/suggestions for these functions).
item is null, because it hasn't been constructed yet out of its parts. The F# compiler compiles tupled parameters as separate actual (IL-level) parameters rather than one parameter of type Tuple<...>. If you look at your compiled code in ILSpy, you will see this signature (using C# syntax):
public static Tuple<string, string, string> calcRelTime(string item_0, string item_1, string item_2)
This is done for several reasons, including interoperability with other CLR languages as well as efficiency.
To be sure, the tuple itself is then constructed from these arguments (unless you have optimization turned on), but not right away. If you make one step (hit F11), item will obtain a proper non-null value.
You can also see these compiler-generated parameters if you go to Debug -> Windows -> Locals in Visual Studio.
As for why it's returning the original list instead of modified one, I can't really say: on my setup, everything works as expected:
> getRelativeTime [] [("x","05/01/2015","y")]
val it : (string * string * string) list = [("x", "y", "17305")]
Perhaps if you share your test code, I would be able to tell more.
And finally, what you're doing can be done a lot simpler: you don't need to write a recursive loop yourself, it's already done for you in the many functions in the List module, and you don't need to accept a tuple and then deconstruct it using tFst, tSnd, and tTrd, the compiler can do it for you:
let getRelativeTime lst =
let calcRelTime (x, time, y) =
let parsed = DateTime.Parse time
let since = DateTime.Now - parsed
let asStr = (floor since.TotalMinutes).ToString()
(x, asStr, y)
List.map calRelTime lst
let getRelativeTime' list =
let calc (a, b, c) = (a, c, (floor (DateTime.Now - (DateTime.Parse b)).TotalMinutes).ToString())
list |> List.map calc
Signature of the function is val getRelativeTime : list:('a * string * 'b) list -> ('a * 'b * string) list
You can deconstruct item in the function declaration to (a, b, c), then you don't have to use the functions tFst, tSnd and tTrd.
The List module has a function map that applies a function to each element in a list and returns a new list with the mapped values.

How to avoid long pattern match based functions?

When using union types with quite a few constructors I almost always find myself implementing lots of logic in single function, i.e. handling all cases in one function. Sometimes I would like to extract logic for single case to separate function, but one cannot have a function accepting only one "constructor" as parameter.
Example:
Assume that we have typical "expression" type :
type Formula =
| Operator of OperatorKind * Formula * Formula
| Number of double
| Function of string * Formula list
[...]
Then, we would like to calculate expression :
let rec calculate efValues formula =
match formula with
| Number n -> [...]
| Operator (kind, lFormula, rFormula) -> [...]
| [...]
Such function would be very long and growing with every new Formula constructor.
How can I avoid that and clean up such code? Are long pattern matching constructs inevitable?
You can define the Operator case of the Formula union using an explicit tuple:
type Formula =
| Operator of (string * Formula * Formula)
| Number of double
If you do this, the compiler will let you pattern match using both Operator(name, left, right) and using a single argument Operator args, so you can write something like:
let evalOp (name, l, r) = 0.0
let eval f =
match f with
| Number n -> 0.0
| Operator args -> evalOp args
I would find this a bit confusing, so it might be better to be more explicit in the type definition and use a named tuple (which is equivalent to the above):
type OperatorInfo = string * Formula * Formula
and Formula =
| Operator of OperatorInfo
| Number of double
Or perhaps be even more explicit and use a record:
type OperatorInfo =
{ Name : string
Left : Formula
Right : Formula }
and Formula =
| Operator of OperatorInfo
| Number of double
Then you can pattern match using one of the following:
| Operator args -> (...)
| Operator { Name = n; Left = l; Right = r } -> (...)
I would say you typically want to handle all the cases in a single function. That's the main selling point of unions - they force you to handle all the cases in one way or another. That said, I can see where you're coming from.
If I had a big union and only cared about a single case, I would handle it like this, wrapping the result in an option:
let doSomethingForOneCase (form: Formula) =
match form with
| Formula (op, l, r) ->
let result = (...)
Some result
| _ -> None
And then handle None in whatever way is appropriate at the call site.
Note that this is in line with the signature required by partial active patterns, so if you decide that you need to use this function as a case in another match expression, you can easily wrap it up in an active pattern to get the nice syntax.

Why does this produce a value restriction exception?

I've created a function that returns a list containing only the even indexes as shown below:
let rec removeOddIdx xs =
match xs with
|[] -> []
|h::t -> (if t.Length % 2 = 0 then
[h]#removeOddIdx t
else
removeOddIdx t)
It works fine when I call it:
removeOddIdx [1;2;3;];;
However when I call it with an empty list:
removeOddIdx [];;
I get a Value Restriction exception - how come?
I've read up on value restrictions but I don't understand why it happens in my case.
Here is the precise error message:
Testing.fs(13,1): error FS0030: Value restriction. The value 'it' has been inferred to have generic type
val it : '_a list
Either define 'it' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
The problem you're having is that the compiler doesn't know what type to give the return value. When you pass it [1;2;3] it can infer that the return type is int list, but if you pass it [], what is the type of the return value? It cannot be inferred from the usage, so you get a value restriction error.
One solution is to give the parameter a type like so:
> removeOddIdx ([]:int list);;
val it : int list = []
The other is to make the function specific rather than generic like this:
> let rec removeOddIdx (xs:int list) =
match xs with
|[] -> []
|h::t -> (if t.Length % 2 = 0 then
[h]#removeOddIdx t
else
removeOddIdx t);;
val removeOddIdx : xs:int list -> int list
> removeOddIdx [];;
val it : int list = []
Outside of the repl this is unlikely to be an issue since the parameter type is likely to be inferred from elsewhere in your code.

error with f# generic follow Expert Fsharp book example

I'm reading Expert F# book and I found this code
open System.Collections.Generic
let divideIntoEquivalenceClasses keyf seq =
// The dictionary to hold the equivalence classes
let dict = new Dictionary<'key,ResizeArray<'T>>()
// Build the groupings
seq |> Seq.iter (fun v ->
let key = keyf v
let ok,prev = dict.TryGetValue(key)
if ok then prev.Add(v)
else let prev = new ResizeArray<'T>()
dict.[key] <- prev
prev.Add(v))
dict |> Seq.map (fun group -> group.Key, Seq.readonly group.Value)
and the example use:
> divideIntoEquivalenceClasses (fun n -> n % 3) [ 0 .. 10 ];;
val it : seq<int * seq<int>>
= seq [(0, seq [0; 3; 6; 9]); (1, seq [1; 4; 7; 10]); (2, seq [2; 5; 8])]
first for me this code is really ugly, even if this is safe, It looks more similar to imperative languages than to functional lang..specially compared to clojure. But the problem is not this...I'm having problems with the Dictionary definition
when I type this:
let dict = new Dictionary<'key,ResizeArray<'T>>();;
I get this:
pruebafs2a.fs(32,5): error FS0030: Value restriction. The value 'dict' has been inferred to have generic type
val dict : Dictionary<'_key,ResizeArray<'_T>> when '_key : equality
Either define 'dict' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
is It ok?...
thanks so much
improve question:
Ok I've been reading about value restriction and I found this helpfull information
In particular, only function definitions and simple immutable data
expressions are automatically generalized
...ok..this explains why
let dict = new Dictionary<'key,ResizeArray<'T>>();;
doesn't work...and show 4 different techniques, although in my opinion they only resolve the error but aren't solutions for use generic code:
Technique 1: Constrain Values to Be Nongeneric
let empties : int list [] = Array.create 100 []
Technique 3: Add Dummy Arguments to Generic Functions When Necessary
let empties () = Array.create 100 []
let intEmpties : int list [] = empties()
Technique 4: Add Explicit Type Arguments When Necessary (similar to tec 3)
let emptyLists = Seq.init 100 (fun _ -> [])
> emptyLists<int>;;
val it : seq<int list> = seq [[]; []; []; []; ...]
----- and the only one than let me use real generic code ------
Technique 2: Ensure Generic Functions Have Explicit Arguments
let mapFirst = List.map fst //doesn't work
let mapFirst inp = List.map fst inp
Ok, in 3 of 4 techniques I need resolve the generic code before can work with this...now...returning to book example...when the compile knows the value for 'key and 'T
let dict = new Dictionary<'key,ResizeArray<'T>>()
in the scope the code is very generic for let key be any type, the same happen with 'T
and the biggest dummy question is :
when I enclose the code in a function (technique 3):
let empties = Array.create 100 [] //doesn't work
let empties () = Array.create 100 []
val empties : unit -> 'a list []
I need define the type before begin use it
let intEmpties : int list [] = empties()
for me (admittedly I'm a little dummy with static type languages) this is not real generic because it can't infer the type when I use it, I need define the type and then pass values (not define its type based in the passed values) exist other way define type without be so explicit..
thanks so much..really appreciate any help
This line
let dict = new Dictionary<'key,ResizeArray<'T>>();;
fails because when you type the ;; the compiler doesn't know what 'key and 'T are. As the error message states you need to add a type annotation, or allow the compiler to infer the type by using it later or make it a function
Examples
Type annotation change
let dict = new Dictionary<int,ResizeArray<int>>();;
Using types later
let dict = new Dictionary<'key,ResizeArray<'T>>()
dict.[1] <- 2
using a function
let dict() = new Dictionary<'key,ResizeArray<'T>>();;
This actually doesn't cause an issue when it's defined all together. That is, select the entire block that you posted and send it to FSI in one go. I get this:
val divideIntoEquivalenceClasses :
('T -> 'key) -> seq<'T> -> seq<'key * seq<'T>> when 'key : equality
However, if you type these individually into FSI then as John Palmer says there is not enough information in that isolated line for the interpreter to determine the type constraints. John's suggestions will work, but the original code is doing it correctly - defining the variable and using it in the same scope so that the types can be inferred.
for me this code is really ugly, even if this is safe, It looks more similar to imperative languages than to functional lang.
I agree completely – it's slightly tangential to your direct question, but I think a more idiomatic (functional) approach would be:
let divideIntoEquivalenceClasses keyf seq =
(System.Collections.Generic.Dictionary(), seq)
||> Seq.fold (fun dict v ->
let key = keyf v
match dict.TryGetValue key with
| false, _ -> dict.Add (key, ResizeArray(Seq.singleton v))
| _, prev -> prev.Add v
dict)
|> Seq.map (function KeyValue (k, v) -> k, Seq.readonly v)
This allows sufficient type inference to obviate the need for your question in the first place.
The workarounds proposed by the other answers are all good. Just to clarify based on your latest updates, let's consider two blocks of code:
let empties = Array.create 100 []
as opposed to:
let empties = Array.create 100 []
empties.[0] <- [1]
In the second case, the compiler can infer that empties : int list [], because we are inserting an int list into the array in the second line, which constrains the element type.
It sounds like you'd like the compiler to infer a generic value empties : 'a list [] in the first case, but this would be unsound. Consider what would happen if the compiler did that and we then entered the following two lines in another batch:
empties.[0] <- [1] // treat 'a list [] as int list []
List.iter (printfn "%s") empties.[0] // treat 'a list [] as string list []
Each of these lines unifies the generic type parameter 'a with a different concrete type (int and string). Either of these unifications is fine in isolation, but they are incompatible with each other and would result in treating the int value 1 inserted by the first line as a string when the second line is executed, which is clearly a violation of type safety.
Contrast this with an empty list, which really is generic:
let empty = []
Then in this case, the compiler does infer empty : 'a list, because it's safe to treat empty as a list of different types in different locations in your code without ever impacting type safety:
let l1 : int list = empty
let l2 : string list = empty
let l3 = 'a' :: empty
In the case where you make empties the return value of a generic function:
let empties() = Array.create 100 []
it is again safe to infer a generic type, since if we try our problematic scenario from before:
empties().[0] <- [1]
List.iter (printfn "%s") (empties().[0])
we are creating a new array on each line, so the types can be different without breaking the type system.
Hopefully this helps explain the reasons behind the limitation a bit more.

Resources