I have the following code
module File1
let convert<'T> x = x
type myType () =
member this.first<'T> y =
convert<'T> y
member this.second<'T> ys =
ys
|> Seq.map this.first<'T>
On the last 'T I get the error Unexpected type arguments. When for example I call let x = myType.first<int> "34" there are no warnings and everything works as expected. Leaving of the type argument gets rid of the warning and the program behaves as intended some of the time.
Can anyone explain what's going on here?
Thanks
In short, you need explicit arguments for your method with type arguments. The error can be fixed by changing
ys
|> Seq.map this.first<'T>
to
ys
|> Seq.map (fun y -> this.first<'T> y)
The error is explained very clearly in this excellent answer, I won't repeat it here. Notice that the error message has been changed between F# 2.0 and F# 3.0.
You don't actually use 'T anywhere in type signatures, so you can just remove 'T without any trouble.
If you need types for querying, I suggest to use the technique in Tomas' answer above.
type Foo() =
member this.Bar (t:Type) (arg0:string) = ()
let f = new Foo()
"string" |> f.Bar typeof<Int32>
Related
Premise: I thought that the piping operator is nothing but syntactic sugar, thus x |> f should be exactly the same as f(x).
Analogously, I thought that f (fun x -> foo) is equivalent to let g = fun x -> foo; f g
But apparently there are differences that I do not understand.
Example 1:
static member contents =
let files = Directory.EnumerateFiles (__SOURCE_DIRECTORY__+ #"\foo\bar.txt")
let fileList = List.ofSeq files
fileList |> List.map (fun f -> TestCaseData(f).SetName(""))
This works fine: TestCaseData expects an arg:obj which is matched by f which in turn in inferred to be a string since fileList is a list of file names.
However the following does not work
static member contents =
let files = Directory.EnumerateFiles (__SOURCE_DIRECTORY__+ #"\foo\bar.txt")
let fileList = List.ofSeq files
List.map (fun f -> TestCaseData(f).SetName("")) fileList
Nothing but the last line has changed. Suddenly f is inferred as obj [] and TestCaseData requires an argument of type obj [] and hence I get an error
Error 1 Type mismatch. Expecting a obj [] list but given a string list
The type 'obj []' does not match the type 'string'
I would have thought that both snippets are equivalent in produce correct code but only the first does?!
Example 2:
[<TestCase("nonsense", TestName="Nonsense")>]
member x.InvalidInputs str =
let lexbuf = Microsoft.FSharp.Text.Lexing.LexBuffer<char>.FromString(str)
Assert.Throws<FatalError> (fun () -> ParsePkg.parse "Dummy path" lexbuf |> ignore)
|> ignore
Above everything works fine.
[<TestCase("nonsense", TestName="Nonsense")>]
member x.InvalidInputs str =
let lexbuf = Microsoft.FSharp.Text.Lexing.LexBuffer<char>.FromString(str)
let ff = fun () -> ParsePkg.parse "Dummy path" lexbuf |> ignore
Assert.Throws<FatalError> (ff)
|> ignore
As you see, all I did was pull out the argument of the assertion by first defining let ff = ... (for readability reasons, say) and suddenly the compiler points to the (ff) argument and complains:
Error 2 This expression was expected to have type TestDelegate but here has type unit -> unit
TestDelegate is a type of NUnit that I am using here and it happens to coincide with unit->unit so I'd assume it would be unified anyway but that does not even matter. Why at all is it possible that the type changes, since again I believe to have done a purely syntactic replacement?!
type inferences is done sequential top to bottom. So in the first case fileList is the first lexical argument.
The information that the fileList is a list of strings is then used in the piping expression. To know whether stringis a legal type for f the signature of TestCaseData is used. As commented, based on the error message TestCaseData probably accepts [<Params>] obj [] making a single string argument valid.
In the second version there's no information to use when determining the type of f other than the signature of TestCaseData and therefor f is inferred to be of type obj []
Similar is true in the other example. Just the other way around. Pulling out the function removes the information that it's supposed to be of type TestDelegate.
At the lexical point the only information available is that it's a function of type unit->unit.
When the function is used at a program point where a TestDelegate is required. The type inference tests whether the function can be used as a TestDelegate and if so, infers the type to be TestDelegate
I had expected that flexible type would minimize the need of explicit upcast, but
type IB =
abstract B : int
type A() =
interface IB with
member this.B = 1
let a = A()
let test (x) = x
let aa = [|a; a|]
let case1 = aa |> Array.map (fun (x: #IB) -> test (x.B))
let case2 = Array.map (fun (x: #IB) -> test (x.B)) aa
Here, there are warnings (less generic than type annotation) on the last 2 lines. The compiler is able to compile case2, but fails at case1, why is that?
It feels odd that the more detailed the compiler can infer, the more code I need to write.
#kvb pointed out there is a simple fix, just to refactor the lambda function into a non inline version.
let fix (x: #IB) =
test x.B
let case1 = aa |> Array.map fix
let case2 = Array.map fix
This works well.
Type inference in F# flows from left to right, so it's not too surprising that piping can break or fix things. However, it's almost always the case that having more type information earlier is helpful, so this result is a bit surprising. The warnings are a subtle indicator that you're doing something wrong. Flexible types seem like they ought to be applicable in many tricky situations, but there are really only a few places where they help. Array.map takes a function of some type 'a -> 'b for some particular 'a and 'b (though there's a little bit of nuance here, since the "particular" types could be type variables), so having a "more generic" argument like #IB -> int is not especially helpful; the compiler will pick some particular subtype of IB during compilation - this is what the warnings are attempting to communicate.
As I said, the different results you see on the different lines are due to the fact that type inference in F# works left to right. In the first case, the information about the type of aa flows into the type checking of the remainder of the expression and so when compiling the lambda the compiler knows that the only possible subtype of IB that will work is A, but because interface implementations are always implicit this causes a compile time error because A doesn't have a publicly available member B. On the other hand, in the second case, when the compiler's trying to check Array.map it doesn't yet know the type of the array it will be applied to, but can check the call in any case because regardless of the subtype it will support the interface method IB.B (implicitly upcasting the argument from whatever subtype of IB it has to just IB). Then when this is applied to aa the compiler specializes the implementation to A, but because of the implicit upcast this still works okay. Intuitively, it seems like the compiler ought to have been able to have inserted the same implicit upcast in the former case, but I think this is probably just a surprising result of the inference algorithm and not an actual bug.
Perhaps more surprising, one possible fix is to just use a let-bound definition (for either the lambda or even as a type-restricted version of Array.map) and skip the flexible type:
let f (x:IB) = test (x.B)
let g (f:IB -> int) = Array.map f
let d' = aa |> g (fun x -> test (x.B))
let d'' = aa |> Array.map f
let c' = g (fun x -> test (x.B)) aa
let c'' = Array.map f aa
So what's happening here? It turns out the compiler does something called "Implicit Insertion of Flexibility for Uses of Functions and Members" (section 14.4.3 of the spec for F# 3.1) which does exactly what you want.
type IB =
abstract B : int
type A() =
interface IB with
member this.B = 1
let a = A()
let test (x) = x
let aa = [|a; a|]
Here the compiler knows that aa is an array of A so type annotation in lambda is not needed but you have to cast x to the interface type because in F# interfaces are implemented explicitely (http://msdn.microsoft.com/en-us/library/ms173157.aspx):
let d = aa |> Array.map (fun x -> test ((x:>IB).B))
Here the compiler at the moment of compiling lambda doesn't know what a type of x is, so you need a type annotation telling that x is implementation of IB interface so you can refer to x.B property directly:
let c = Array.map (fun (x: #IB) -> test (x.B)) aa
Ok, so I'm basically trying to add the bind operator to the option type and it seems that everything I try has some non-obvious caveat that prevent me from doing it. I suspect is has something to do with the limits of the .NET typesystem and is probably the same reason typeclasses can't be implemented in user code.
Anyways, I've attempted a couple of things.
First, I tried just the following
let (>>=) m f = ???
realizing that I want to do different things based on the type of m. F# doesn't allow overloads on function but .NET does allow them on methods, so attempt number two:
type Mon<'a> =
static member Bind(m : Option<'a>, f : ('a -> Option<'b>)) =
match m with
| None -> None
| Some x -> f x
static member Bind(m : List<'a>, f : ('a -> List<'b>)) =
List.map f m |> List.concat
let (>>=) m f = Mon.Bind(m, f)
No dice. Can't pick a unique overload based on previously given type info. Add type annotations.
I've tried making the operator inline but it still gives the same error.
Then I figured I could make the >>= operator a member of a type. I'm pretty sure this would work but I don't think I can hack it in on existing types. You can extend existing types with type Option<'a> with but you can't have operators as extensions.
That was my last attempt with this code:
type Option<'a> with
static member (>>=) (m : Option<'a>, f : ('a -> Option<'b>)) =
match m with
| None -> None
| Some x -> f x
"Extension members cannot provide operator overloads. Consider defining the operator as part of the type definition instead." Awesome.
Do I have any other option? I could define separate functions for different monads in separate modules but that sounds like hell if you want to use more than one version in the same file.
You can combine .NET overload resolution with inline/static constraints in order to get the desired behaviour.
Here's a step by step explanation and here's a small working example for your specific scenario:
type MonadBind = MonadBind with
static member (?<-) (MonadBind, m:Option<'a>, _:Option<'b>) =
fun (f:_->Option<'b>) ->
match m with
| None -> None
| Some x -> f x
static member (?<-) (MonadBind, m:List<'a>, _:List<'b>) =
fun (f:_->List<'b>) ->
List.map f m |> List.concat
let inline (>>=) m f : 'R = ( (?<-) MonadBind m Unchecked.defaultof<'R>) f
[2; 1] >>= (fun x -> [string x; string (x+2)]) // List<string> = ["2"; "4"; "1"; "3"]
Some 2 >>= (fun x -> Some (string x)) // Option<string> = Some "2"
You can also specify the constraints 'by hand', but when using operators they're inferred automatically.
A refinement of this technique (without the operators) is what we use in FsControl to define Monad, Functor, Arrow and other abstractions.
Also note you can use directly Option.bind and List.collect for both bind definitions.
Why do you need to (re-define) "bind"? For starters, Option.bind is already defined.
You can use it for defining a "computational expression builder" (F# name for monadic "do" syntax sugar).
See previous answer.
I keep running into the following problem:
(System.Console.ReadLine ()).Split [|'('; ')'|]
|> Array.filter (fun s -> not (System.String.IsNullOrEmpty (s)))
|> Array.map (fun s -> s.Split [|','|])
|> Array.map (fun s -> Array.map (fun t -> t.Trim ()) s) (* t.Trim () is underlined with a red squiggly line *)
|> [MORE CODE]
The error associated with the red squiggly line is:
Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
But when the mouse pointer hovers over t, IntelliSense correctly says that t is of type string.
I can bypass the error by writing fun (t : string) -> [CODE], but I wonder why Visual Studio draws the squiggly line at all when it is already detecting the type of the variable correctly. Is this a simple bug in the trial build, or am I misunderstanding something about F#'s type inferencing?
Thanks in advance for your responses.
There is some gap between F# intellisense and F# type checker.
The type checker works from left to right in order. Your problem can be fixed be changing:
fun s -> Array.map (fun t -> t.Trim()) s
to
fun s -> s |> Array.map (fun t -> t.Trim())
Since type of s is available before using Array.map, the type checker is able to infer type of t.
Remarks:
This error usually occurs when using instance methods. You could replace these methods by static functions with extra type annotation and refactor to make your code more composable:
let split arr (s: string) = s.Split arr
let trim (s: string) = s.Trim()
System.Console.ReadLine()
|> split [|'('; ')'|]
|> Array.filter (not << System.String.IsNullOrEmpty)
|> Array.map (split [|','|])
|> Array.map (Array.map trim)
how does one convert from a list of characters to a string?
To put it another way, how do I reverse List.ofSeq "abcd"?
UPDATE: new System.String (List.ofSeq "abcd" |> List.toArray) |> printfn "%A" seems to work fine, with or without new, but List.ofSeq "abcd" |> List.toArray) |> new System.String |> printfn "%A" fails. Why?
I asked a similar question once before. It seems object constructors aren't composable so you can't pass them as a function.
List.ofSeq "abcd" |> List.toArray |> (fun s -> System.String s) |> printfn "%A"
List.ofSeq "abcd" |> List.toArray |> (fun s -> new System.String(s)) |> printfn "%A"
Update
Constructors are first-class functions as of F# 4.0
List.ofSeq "abcd" |> List.toArray |> System.String |> printfn "%A"
Working with strings in F# is sometimes a bit uncomfortable. I would probably use the same code as Dario. The F# grammar doesn't allow using constructors as first class functions, so you unfortunately cannot do the whole processing in a single pipeline. In general, you can use static members and instance methods as first class functions, but not instance properties or constructors.
Anyway, there is a really nasty trick you can use to turn a constructor into a function value. I would not recommend actually using it, but I was quite surprised to see that it actually works, so I thought it may be worth sharing it:
let inline ctor< ^R, ^T
when ^R : (static member ``.ctor`` : ^T -> ^R)> (arg:^T) =
(^R : (static member ``.ctor`` : ^T -> ^R) arg)
This defines a function that will be inlined at compile time, which requires that the first type parameter has a constructor that takes a value of the second type parameter. This is specified as a compile-time constraint (because .NET generics cannot express this). Also, F# doesn't allow you to specify this using the usual syntax for specifying constructor constraints (which must take unit as the argument), but you can use the compiled name of constructors. Now you can write for example:
// just like 'new System.Random(10)'
let rnd = ctor<System.Random, _> 10
rnd.Next(10)
And you can also use the result of ctor as first-class function:
let chars = [ 'a'; 'b'; 'c' ]
let str = chars |> Array.ofSeq |> ctor<System.String, _>
As I said, I think this is mainly a curiosity, but a pretty interesting one :-).
Your approach:
new System.String (listOfChars |> List.toArray)
is the solution I usually end up with too.
F#'s grammar/type inference system simply seems unable to recognize a .NET constructor like new String as a curried function (which prevents you from using pipelining).
Just faced similar problem, and came up with this solutions:
List.fold (fun str x -> str + x.ToString()) "" (List.ofSeq "abcd")