f#: Signature file causing Intellisense to complain? - f#

Given the following code...
type IMyInterface =
abstract BoolA : bool
abstract BoolB : bool
let myFn _boolVal (_i: IMyInterface) = if _boolVal then _i.BoolA else _i.BoolB
let myFnTrue = myFn true
let myFnFalse = myFn false
... Intellisense complains, and the compiler fails, if I create a signature file with this in it:
type IMyInterface =
abstract BoolA : bool
abstract BoolB : bool
val myFnTrue : (IMyInterface -> bool)
val myFnFalse : (IMyInterface -> bool)
The error is Error 10 Module 'MyModule' contains val myFnTrue : ('_a -> bool) when '_a :> MyModule.IMyInterface but its signature specifies val myFnTrue : (MyModule.IMyInterface -> bool) The types differ. (A similar error is reported for myFnFalse.)
I feel like an idiot, not being able to figure this out. What am I doing wrong? (Bracing for the "duh" answer...)

In your signature file, myFnTrue and myFnFalse have the signature IMyInterface -> bool but in your implementation 'a -> bool with the constraint 'a :> IMyInterface (due to automatic generalization), that is, the implementation is generic and the signature is not.
The simplest solution is changing your implementation to this:
let myFnTrue i = myFn true i
let myFnFalse i = myFn false i

Related

Is it possible to write a generic based on a record with a named field?

I have some code which has a lot of repetition.
type RecordA = {
Name: string
// ...
}
type RecordB = {
Name: string
// ...
}
val getTheHandler: (name: string) -> (() -> ())
let handleA (record: RecordA) =
(getTheHandler record.Name) ()
let handleB (record: RecordB) =
(getTheHandler record.Name) ()
I'm wondering if it is possible to write some generic function that would let me simplify/refactor the getTheHandler record.Name. In trying to refactor that snippet the compiler wants to choose one record type of the other.
So trying this, I get a compiler error:
let shorter (record: 'T) =
(getTheHandler record.Name) ()
// later:
shorter myRecordA // FS0001: This expression was expected to have type RecordB but here has type RecordA
Is this possible? Is the only way to make this work to add a member function to each record type?
Yes, it is possible with SRTP - see here: Partial anonymous record in F#
Here's an example using your use case:
let getTheHandler (name: string) () = printfn $"{name}"
let inline handle (r: ^T) =
(^T : (member Name: string) r)
let ra: RecordA = { Name = "hello" }
let rb: RecordB = { Name = "world" }
handle ra // "hello"
handle rb // "world"
I'd also say though, a little repetition isn't that bad. SRTPs can be wonderful, but can lead down a path of getting way too happy with abstraction and sometimes compile-time slow downs. Using it judiciously like this isn't that bad though.
Just for the record, you can also solve this problem by using ordinary object-oriented interfaces. This is something that works quite well with functional design in F# and it is quite clean. There is some more work involved in explicitly implementing the interfaces, but the up side is that you end up with more clear explicit code (and the interface can model the intention better than just a member name):
To define and implement an interface:
type INamed =
abstract Name : string
type RecordA =
{ Name: string }
interface INamed with
member x.Name = x.Name
type RecordB =
{ Name: string }
interface INamed with
member x.Name = x.Name
To use this:
let getTheHandler (name:string) =
fun () -> printfn "Hi %s" name
let handle (record: INamed) =
(getTheHandler record.Name) ()
You also can solve this by using a higher-order function. By doing the selection through a function. It will become generic.
type RecordA = {
Name: string
}
type RecordB = {
Name: string
}
let getTheHandler name = printfn $"{name}"
let handle chooser record =
fun () -> getTheHandler (chooser record)
let ra : RecordA = {Name="Hello"}
let rb : RecordB = {Name="World"}
let name1 = ra |> handle (fun r -> r.Name)
let name2 = rb |> handle (fun r -> r.Name)
name1 ()
name2 ()

Is it possible in F# to factor out type constraints

I'm using the below bit of code
// Neat method of finding the TryParse method for any type that supports it.
// See https://stackoverflow.com/a/33161245/158285
let inline tryParseWithDefault (defaultVal:'a) text : ^a when ^a : (static member TryParse : string * ^a byref -> bool) =
let r = ref defaultVal
if (^a : (static member TryParse: string * ^a byref -> bool) (text, &r.contents))
then !r
else defaultVal
but I notice that the type constraint
^a : (static member TryParse : string * ^a byref -> bool
is used twice. Is there any way to do the following
constraint Parsable a = ( a : ^a : (static member TryParse : string * ^a byref -> bool)
and use Parsable like
// Neat method of finding the TryParse method for any type that supports it.
// See https://stackoverflow.com/a/33161245/158285
let inline tryParseWithDefault (defaultVal:'a) text : Parsable =
let r = ref defaultVal
if (^a : (Parsable) (text, &r.contents))
then !r
else defaultVal
As the existing answer says, you do not explicitly need to repeat the constraint in the type signature because the F# compiler can infer it. One more way of further factoring out the code that involves the type constraint would be to just have tryParse function which invokes the TryParse method (and has the type constraint) and then call this function from your tryParseWithDefault.
This way, you separate the "core" logic of invoking the member from any extra logic. When you do this, you again don't need to repeat the constraint, because the compiler infers it:
let inline tryParse text =
let mutable r = Unchecked.defaultof<_>
(^a : (static member TryParse: string * ^a byref -> bool) (text, &r)), r
let inline tryParseWithDefault (defaultVal:'a) text =
match tryParse text with
| true, v -> v
| _ -> defaultVal
There is no way I know of, however, you can simplify the function by letting F# infer the signature:
let inline tryParseWithDefault defaultVal text =
let r = ref defaultVal
if (^a : (static member TryParse: string * ^a byref -> bool) (text, &r.contents))
then !r
else defaultVal

how do I get this signature in f#: val sigF : int -> bool -> float -> string

I am using FSI, how do I go from bool to float?
have: let sigF 1 = 1=1 gets: val sigF : int -> bool
need the function that has the signature: val sigF : int -> bool -> float -> stringĀ 
can you not convert bool to float?
are there any resources on understanding signatures?, I cant find any examples where bool goes to anything else, do i need to understand "currying" better? (I am completely new to functional programming)
Unless this is a puzzle or a challenge, you can assume that i:int -> b:bool -> f:float -> string is the same as int -> bool -> float -> string. The only difference is that the former also includes names of the parameters of the function - which is just extra information that you can ignore and that does not change the meaning much.
You get the parameter names if you do something like this:
> let sigF (i:int) (b:bool) (f:float) = "";;
val sigF : i:int -> b:bool -> f:float -> string
The ingineous solution from Michael avoids naming the parameters by instead using patterns (matching against concrete values), which gives you the right signature, but also a plenty of warning because the function will fail if called with any other value as argument:
> let sigF 7 true 0.3 = "done";;
warning FS0025: Incomplete pattern matches on this expression.
For example, the value '0.0' may indicate a case not covered by the pattern(s).
warning FS0025: Incomplete pattern matches on this expression.
For example, the value 'false' may indicate a case not covered by the pattern(s).
warning FS0025: Incomplete pattern matches on this expression.
For example, the value '0' may indicate a case not covered by the pattern(s).
val sigF : int -> bool -> float -> string
Another solution that gives you the right signature, but without the warnings is to use _ pattern with a type annotation - this says that you are ignoring the argumnet, but it gives an explicit type to it:
> let sigF (_:int) (_:bool) (_:float) = "";;
val sigF : int -> bool -> float -> string
let f 7 true 0.3 = "done";;
7 true and .03 (all imply function inputs) while after the = is an output
val f : int -> bool -> float -> string
A function having the signature val sigF : int -> bool -> float -> string could be for example let sigF (i:int) (b:bool) (f:float) = "". The last in the row of -> symbols is the output, all others are inputs.

Is it possible to use explicit member constraints on static fields?

Using F#, I had the following (simplified), which works fine:
type MyInt =
struct
val Value: int
new v = { Value = v }
end
static member inline name() = "my_int" // relevant line
let inline getName (tp: ^a): string = (^a: (static member name : unit -> string) ())
It seems to me that the statically resolved member signature from the explicit member constraint requires a function. I was wondering if it can also be used with a field instead. I tried a few things:
The following will compile, but won't work and will fail with the error
error FS0001: The type 'MyInt' does not support the operator 'get_name'
type MyInt =
//...
static member inline name = "my_int"
let inline getName (tp: ^a): string = (^a: (static member name : string) ())
Removing the () to prevent it from trying to call the gettor is a syntax error. If I change it to actually implement the gettor, it works (but that's essentially the same as the original code).
type MyInt =
// ...
static member inline name with get() = "my_int"
let inline getName (tp: ^a): string = (^a: (static member name : string) ())
Is there a way to get, using explicit member constraints or similar means, the compiler to find the static field? Or is this simply a limitation of the syntax of constraints?
Update:
Surprisingly, it does work with instance fields, or as in this case, struct fields: using (^a: (member Value: 'b) ()), which will call the member Value.

Is there a way to specify named arguments for a function in an F# constructor?

Is there a way to name the function arguments in a constructor?
type UnnamedInCtor(foo: string -> string -> bool) =
member this.Foo: string -> string -> bool = foo
member this.Bar: a:string -> b:string -> bool = foo
member this.Fizz = foo
//Does not compile
type NamedInCtor(foo: a:string -> b:string -> bool) =
member this.Foo: string -> string -> bool = foo
member this.Bar: a:string -> b:string -> bool = foo
member this.Fizz = foo
I think that it's impossible in F#, however you can use type abbreviations if you want to document what foo represents:
// Compiles
type aToBToC = string -> string -> bool
type NamedInCtor(foo: aToBToC) =
member this.Foo: string -> string -> bool = foo
member this.Bar: a:string -> b:string -> bool = foo
member this.Fizz = foo
You would need to de-curry the function in your constructor:
type NamedInCtor(a, b) =
member this.Foo: string -> string -> bool = a b
member this.Bar: string -> string -> bool = a b
member this.Fizz = a b
Note that a and b are implicitly typed here. You should trust the compiler to do this as much as possible, because it makes your code much more readable.
Remember, functions are first class types and traditional objects are discouraged. What you're asking is essentially "can I name and access some arbitrary subset of this type?" The answer to that is no. If you want that behavior, then you must structure your functions to request it.

Resources