Can't create generic partial application of a function in F# - f#

I am looking for a way to fix this very certain situation: I have a function-factory toF that takes a function-parameter g and based on it creates a resulting function f
let toF g =
let f x = g x
f
let f = toF id
The problem is that I get a
error FS0030: Value restriction. The value 'f' has been inferred to have generic type val f : ('_a -> '_a) Either make the arguments to 'f' explicit or, if you do not intend for it to be generic, add a type annotation.
I can add type annotations (which I am not eager to do) or alternatively I can rewrite it like this:
let f' g x = g x
let f x = f' id x
I don't like doing it this way because if I do then every time I call f I am making another call to f' specifying g along the way. While the first example keeps g in the closure and requires just one call.
UPDATE (for Tomas)
I have tried what you suggested.
let toF g =
printfn "Creating f using g"
let f x =
printfn "x: %A" x
g x
f
let f x = toF id x
let ``test``() =
1 |> f |> f |> ignore
What basically is happening is that every time I make a call to the function f it first calls toF id getting a composed function and only then calls that composed function on x.
Creating f using g
x: 1
Creating f using g
x: 1
So essentially the composition is created on every call to f via subsequent call to toF. But this is exactly what I was trying to avoid. By defining let f = toF id I was hoping to get a closure one sigle time and then be able to call it immediately. So the output I am expecting would be:
Creating f using g
x: 1
x: 1
UPDATE 2
The following doesn't work either for the very same reason:
let toF g =
printfn "Creating f using g"
let f x =
printfn "x: %A" x
g x
f
let f() = toF id
let fg = f()

You just need to make f a syntactic function:
let toF g =
let f x = g x
f
let f x = toF id x
When f is not syntactically a function (taking parameter) but a value, you hit the "value restriction" error. I'm not going to try to explain it here, because there is already great info in previous posts like: Understanding F# Value Restriction Errors.
EDIT - If you want to make sure that g gets called only once (but still want the code to be generic) then the easiest way is to add unused unit parameter (to make it a function) and then call it once (which determines the generic parameters) and use the result multiple times:
let toF g =
let f x = g x
f
let f () = toF id
let fg = f ()
fg 1
fg 2
This is sadly needed, because having a function that is generic, but is returned by some computation would actually create a subtle hole in the type system - that's the reason for the "value restriction".

The easiest solution is to just add a type annotation. Assuming that there's only one real type you care about, this is completely straightforward:
let toF g =
let f x = g x
f
let f : _ -> int = toF id
If you really need to call f at different types, then you can wrap it in a generic type:
type F<'t>() =
static member val f : _ -> 't = toF id
let blah = F.f "blah"
let one = F.f 1

Related

odd type inference issue with 'validation', in F#

using the lib 'FsToolkit.ErrorHandling'
and the following code:
let f x =
if x % 2 = 0 then Ok $"even {x}" else Error $"odd {x}"
let xx =
validation {
let! a = f 1
and! b = f 2
and! c = f 3
return $"{a} {b} {c}"
}
printfn $"{xx.GetType()}"
The output is a
Result<string, string list>
Or, more specifically:
Microsoft.FSharp.Core.FSharpResult2[System.String,Microsoft.FSharp.Collections.FSharpList1[System.String]]
But the IDE (Rider) sees it differently:
Is this an expected behavior for some reason? or could it be a bug?
Validation<'a, 'err> is a type alias for Result<'a, 'err list>:
https://github.com/demystifyfp/FsToolkit.ErrorHandling/blob/f5019f10c4418426a2e182377be06beecd09876b/src/FsToolkit.ErrorHandling/Validation.fs#L3
This doesn't create a new type but creates a new way to refer to an existing type, which means that they can be used interchangeably.

F# type with `and` and Lazy?

I read the following type definition. What does it do?
type StreamCell<'a> =
| Nill
| Cons of 'a * Stream<'a>
and Stream<'a> = Lazy<StreamCell<'a>>
I tried to define the value with the type.
let x = Lazy(1::2::Nill) // Type is Lazy<list<int>>
let y = Lazy(Nill::1) // Lazy<StreamCell<obj>>
I thought the type of x and y should be StreamCell?
The and in F# exists to define recursive types. In most other languages there exists no order. Once you define a class, function and so on. You can access it. But in F# order is important. You only can access thinks that are already defined.
Because of this, usually it would not be possible to define recursive types, or in generall circular types. What i think is a good idea. But sometimes, you want this, and in this case, you must define the types that should be recursive with an and.
A simple example would be
type A = A of B
type B = B of A
and this will fail. Because when you define A, there is no B. So B must be defined before A. But you cannot define B before A because it depends on A.
So instead of using type you use and instead.
type A = A of B
and B = B of A
You cannot create a value of this type because it would be infinite, but it's only for understanding the problem. Next, your example is not the best, because.
and Stream<'a> = Lazy<StreamCell<'a>>
is only a Type Alias. Here you define Stream<'a> as an alias to Lazy<StreamCell<'a>>. But the compiler will usually not use Stream<'a>. This only helps if you would write the type manually in your function definitions. Your definition could also be.
type StreamCell<'a> =
| Nill
| Cons of 'a * Lazy<StreamCell<'a>>
In your example
let x = Lazy(1::2::Nill)
You use :: and this IS NOT the Cons you define with your stream. You will use the cons operator that is defined with F#, and that is the built-in list. This is the reason why you see Lazy<List<int>> as a type.
If you want to define your stream with two values you need to write.
let x = Cons(1,lazy Cons(2, lazy Nill))
As a general note i would rename Cons to Next or something else. To avoid confusion and create helper function to create Nill and Next values.
Addition
and can also be used to change the Order of definition, and make it more obvious, which types belong together.
type Person = {
Name: string
Sex: Sex
}
and Sex =
| Male
| Female
let person = { Name="David"; Sex=Male }
Example
Here is a full-blown example how i would do a Stream type on what you provided.
type Stream<'a> =
| Nill
| Next of 'a * Lazy<Stream<'a>>
let nill = Nill
let next h t = Next(h,t)
let rec unfold gen state =
match gen state with
| None -> Nill
| Some(x,state) -> next x (lazy unfold gen state)
let rec fold f acc xs =
match xs with
| Nill -> acc
| Next(h,t) -> fold f (f acc h) (t.Force())
let rec rev stream =
fold (fun acc x -> next x (lazy acc)) nill stream
let toList stream =
fold (fun acc x -> x::acc ) [] (rev stream)
let rec take x stream =
if x > 0 then
match stream with
| Nill -> Nill
| Next(h,t) -> next h (lazy take (x-1) (t.Force()))
else
Nill
let fromTo start stop =
unfold (fun acc -> if acc<stop then Some(acc,acc+1) else None) start
let x = next 1 (lazy next 2 (lazy next 3 (lazy nill)))
let y = next 1.0 (lazy next 2.0 (lazy next 3.0 (lazy nill)))
printfn "%A" (toList (take 2 x))
printfn "%A" (toList (take 2 y))
printfn "%A" (toList (take 2 (fromTo 1 100)))
printfn "%A" (toList (take 5 (fromTo 1 1_000_000_000)))

F# - Error when composing a function with itself

In F# I can define an add1 function
let add1 x = x + 1
I can then define an add2 as the add1 function called on itself
let add2 x = add1 (add1 x)
Or by composing the add1 function with itself
let add2 = add1 >> add1
I was trying to implement the lambda calculus combinators in F#, the first being Identity
let I x = x
I then tried to define the Identity of Identity
let II = I >> I
But this caused the following compilation error:
Value restriction. The value 'II' has been inferred to have generic
type
val II : ('_a -> '_a) Either make the arguments to 'II' explicit or, if you do not intend for it to be generic, add a type
annotation
I can however define it as
let II x = I (I x)
I'm new to F# and am curious why?
This error has nothing to do with function composition itself, it's about Value Restriction. It happens because F# compiler infers types as generic as possible, but although it can easily generalize function, it can't generalize value (even though your value is in fact a function).
This answer can help you avoid this problems, but basically you should specify an input parameter:
let II x = (I>>I) x
or
let II x = I >> I <| x
#kagetogi is right.
The F# compiler wants to resolve values into concrete types and it will try to do so as soon as you use the function the first time. So this fails:
let I x = x
let II = I >> I
But this works:
let I x = x
let II = I >> I
II 5 |> printfn "%A"
Here II has type int->int. Which means that the following fails:
let I x = x
let II = I >> I
II 5 |> printfn "%A"
II 5.0 |> printfn "%A"
Because the second call is expecting an int not a float.
That is why in F# the pipe |> operator is preferred over the composition operator >>.
let I x = x
let II x = x |> I |> I
let II' x = x |> (I >> I)
Now finally II has generic type 'a->'a.
They both achieve function composition in the end.
Adding the code annotation also works:
let II<'a> : 'a->'a = I >> I

How to avoid changing parameter order

I am currently doing some of the excercises from exercism.io. One of the excercises is summing up all numbers in a sequence that are a multiple of one or more numbers from a different sequence. Splitting the problem into smaller functions seemed like a good idea and i came up with this:
let multipleOf m n =
n % m = 0
let anyMultipleOf (m: int list) n =
m
|> Seq.exists (multipleOf n)
let sumOfMultiples m n =
[1..n-1]
|> Seq.filter (anyMultipleOf m)
|> Seq.sum
The idea being, that i can use partial application to "bake in" the m parameter into my (any)multipleOf functions. But this code doesn't work the way i want it to, because Seq.exists (multipleOf n) actually applies n as my m parameter.
How can i refactor this code without having to reverse the parameter order of my multipleOf function?
Note: I want a solution that uses my multipleOf function inside my anyMultipleOf function. This solution works, but doesn't reuse my first function:
let anyMultipleOf (m: int list) n =
m
|> Seq.exists (fun x -> n % x = 0)
I did type in a suggestion to use flip, but the obvious thing to do is this:
let anyMultipleOf (m: int list) n =
m
|> Seq.exists (fun x -> multipleOf x n)
flip is a nice tool to have, but pipelines of flipped functions are painful to read.
While it's unclear to me why you don't redefine anyMultipleOf to take the the list as the last argument, you can always use flip:
let flip f x y = f y x
This function exists in Haskell, but not in FSharp.Core, which is the reason you'd have to define it yourself.
As an example, flip anyMultipleOf returns a function with the type int -> int list -> bool, which, if I understand the question correctly, is what you want.
You can define yourself a function which just do that :
Takes a function and 2 arguments in reversed order and return the result of applying the arguments in the right order to the function
let flip f y x = f x y

`use` keyword doesn't work with curry form?

let make f =
printfn "1"
use file = File.CreateText("abc.txt")
let v = f file
printfn "2"
v
let f (x: StreamWriter) (y:int) =
printfn "3"
x.WriteLine("{0}", y)
let a = make f
> 1
> 2
> val a : (int -> unit)
a 8
System.ObjectDisposedException: The object was used after being disposed.
When compiling this doesn't give me any error or warning, but in the runtime it triggers such error.
Do I have to use the full version let make f y = ... to avoid the curried form?
The use keyword ensures that the Dispose method is called at the end of the lexical scope. This means that it calls it when a value is returned from your make function. The problem is that in your case, the returned value is a function that is called later.
In other words, what you're writing could be also seen as:
let make f =
printfn "1"
use file = File.CreateText("abc.txt")
printfn "2"
(fun y -> f file y)
Here, you can see why this does not work. If you want to call the function f with all arguments before the file is disposed of, you need to write something like this:
let make f y =
printfn "1"
use file = File.CreateText("abc.txt")
let v = f file y
printfn "2"
v

Resources