Why this piece of code is working on my fsi, but can't build the project? I am using vs2010 and F# 2.0 ...Any ideas that I am missing something?
let arg = [#"C:\Temp\bin"; #"C:\temp\xml"]
arg|> List.map(fun (s) -> printfn "%s" s)
getting the error telling that it was expecting int, how?
Error 1
Type mismatch. Expecting a string list -> int but given a string list -> 'a list
The type 'int' does not match the type ''a list'
C:\Users\Ebru\Documents\Visual Studio 2010\Projects\WinFind\WinFind\Program.fs
I'm guessing you actually wrote
[<EntryPoint>]
let Main(args) =
let arg = [#"C:\Temp\bin"; #"C:\temp\xml"]
arg|> List.map(fun (s) -> printfn "%s" s)
and an EntryPoint method (e.g. Main()) must return an int.
this snippet compiles on my machine, but the mapping seems weird. I think you really what to do this:
let arg = [#"C:\Temp\bin"; #"C:\temp\xml"]
arg|> List.iter (fun s -> printfn "%s" s)
which is the same as:
let arg = [#"C:\Temp\bin"; #"C:\temp\xml"]
arg|> List.iter (printfn "%s")
Regards,
forki
Related
How to resolve this problem with type inference?
open Microsoft.FSharp.Linq.RuntimeHelpers
open System
open System.Linq.Expressions
open Accord.Math.Optimization
module Vector=
let compareScalarProcut(a:double[])(b:double[])(greaterOrEqualThen:float)=
Array.map2 (*) a b
|> Array.sum
|> fun x-> x >= greaterOrEqualThen
module Lambda =
let toExpression (``f# lambda`` : Quotations.Expr<'a>) =
``f# lambda``
|> LeafExpressionConverter.QuotationToExpression
|> unbox<Expression<'a>>
let LambdaExpression (coefficients:double[]) =
<# Func<double[], bool>(fun i -> (Vector.compareScalarProcut(i,coefficients,0)) #>
|> Lambda.toExpression
You're calling your function incorrectly. It's a "normal" F# function that takes arguments separated by whitespace, instead of a tuple of arguments separated by commas. Try this instead:
Vector.compareScalarProcut i coefficients 0.0
My question is this:
How can I splice the expressions from a list into a quotation when I don't know the number and types of those expressions at design time?
At the bottom I've included the full code for a type provider. (I've stripped the concept down to demonstrate the problem.) My issue occurs at these lines:
let func = ProvidedMethod((*...*), InvokeCode = fun args ->
<## let stringParts =
args
|> List.mapi (fun i arg ->
if paramTypes.[i] = typeof<int> then
sprintf "%i" (%%arg: int)...
On the lambda parameter arg, I get the following error:
error FS0446: The variable 'arg' is bound in a quotation but is used as part of a spliced expression. This is not permitted since it may escape its scope.``
I can't figure out how to write code such that I "extract" the parameter values when the numbers and types of the values are not known at provider-design time (although they will be known at compile time).
When I DO know of a parameter's existence and type at design time, I can do this:
printfn "%A" (%%args.[0]: int)
But I can't figure out how to get from the Expr list input to an obj list within the quotation.
Here's the full type provider code:
[<TypeProvider>]
type SillyProviderDefinition(config: TypeProviderConfig) as self =
inherit TypeProviderForNamespaces()
let sillyType = ProvidedTypeDefinition(THIS_ASSEMBLY, NAMESPACE, "SillyProvider", Some typeof<obj>)
do sillyType.DefineStaticParameters([ProvidedStaticParameter("argTypes", typeof<string>)], fun typeName args ->
let retType = ProvidedTypeDefinition(typeName, Some typeof<obj>)
let paramTypes =
(args.[0] :?> string).Split([|'|'|])
|> Array.map (function
| "int" -> typeof<int>
| "string" -> typeof<string>
| x -> failwithf "Invalid argType %A. Only string or int permitted" x)
let parameters =
paramTypes
|> Array.mapi (fun i p -> ProvidedParameter(sprintf "arg%i" i, p))
|> Array.toList
let func = ProvidedMethod("Stringify", parameters, typeof<string>, IsStaticMethod = true, InvokeCode = fun args ->
<## let stringParts =
args
|> List.mapi (fun i arg ->
if paramTypes.[i] = typeof<int> then
sprintf "%i" (%%arg: int)
elif paramTypes.[i] = typeof<string> then
(%%arg: string)
else
failwith "Unexpected arg type")
//printfn "%A" (%%args.[0]: int)
String.Join("", stringParts) ##>)
do retType.AddMember func
do sillyType.AddMember retType
retType)
do self.AddNamespace(NAMESPACE, [sillyType])
As a minimal example, let's say that we have list with types and a list with some quotations (in the context of type provider, you have the list of types and args is the list of quotations, possibly also containing the this instance):
open Microsoft.FSharp.Quotations
let tys = [ typeof<int>; typeof<string> ]
let args = [ Expr.Value(42); Expr.Value("test"); ]
We want to construct an expression that calls formatInt or formatString depending on the type and then concatenates all the formatted strings:
let formatInt (n:int) = string n
let formatString (s:string) = s
Now, it's important to distinguish what happens in the provided quoted code (quote-level) and in the ordinary code that is run to generate the quotation (code-level). At code-level, we iterate over all the types and quoted arguments and generate a list of quotations with calls to formatInt or formatString - those can be typed Expr<string> because they have the same type:
let formattedArgList =
[ for t, e in List.zip tys args ->
if t = typeof<int> then <# formatInt %%e #>
elif t = typeof<string> then <# formatString %%e #>
else failwith "!" ]
Now you can build a list expression by calling fold at code-level and using the list :: operator at the quote-level:
let listArgExpr =
formattedArgList
|> List.fold (fun state e -> <# %e::%state #>) <# [] #>
And now you can construct a quotation with quoted String.concat call:
<# String.concat "," %listArgExpr #>
When I run this FsUnit test with NUnit 2.6.3,
let f xs = Some (List.map ((+) 2) xs)
[<Test>]
let test() =
f []
|> should equal (Some [])
I get:
Result Message:
Expected: <Some([])>
But was: <Some([])>
Result StackTrace:
at FsUnit.TopLevelOperators.should[a,a](FSharpFunc`2 f, a x, Object y)
The test fails even though the Expected and Actual in the message are the same. What happened?
The reason is that FsUnit uses untyped mechanism under the hood so Expected is inferred as object by the type checker (see the Object y part in the stacktrace).
A workaround is to add type annotation for generic values i.e.
[<Test>]
let test() =
f []
|> should equal (Some ([]: int list))
Several people have been bitten by this e.g. Weird None behaviour in type providers.
Beauty of fluent assertions is pointless to me once they're no longer type-safe. I suggest to create a type-safe alternative:
let shouldEqual (x: 'a) (y: 'a) =
Assert.AreEqual(x, y, sprintf "Expected: %A\nActual: %A" x y)
This is because your two empty lists are of different types. See the types of actual and expected in this version of your test:
[<Test>]
let test() =
let expected = Some []
let actual = f []
actual |> should equal expected
expected is 'a list option and actual is int list option, so they are not equal.
If you give the compiler some hints about the expected result then it will work.
[<Test>]
let test() =
f []
|> should equal (Some List.empty<int>)
The Tour of f# has a sample similar to this code:
let swap_tuple (a, b) = (b, a)
let result = swap_tuple ("one", "two")
printfn "%A" result // prints ("two", "one")
So the code above work. But why does this code:
let swap_tuple (a, b) = (b, a)
printfn "%A" swap_tuple ("one", "two")
throws this compilation error:
error FS0001:
Type mismatch. Expecting a 'a -> 'b -> 'c but given a 'a -> unit
The type ''a -> 'b' does not match the type 'unit'
What is wrong in the second version?
In your second version, your format string has just the one format specifier, but the printfn statement has been suppplied with two. You need to use () to group together swap_tuple with its arguments into a single argument.
let swap_tuple (a, b) = (b, a)
printfn "%A" (swap_tuple ("one", "two") )
As an alternative to Jimmy's answer, you could also use the pipeline operators:
printfn "%A" <| swap_tuple ("one", "two")
or
("one", "two")
|> swap_tuple
|> printfn "%A"
This compiles and works:
let rec HelloEternalWorld _ =
Console.ReadLine() |> printf "Input: %s\n"
HelloEternalWorld 0
HelloEternalWorld 0
This does not compile:
let rec HelloEternalWorld =
Console.ReadLine() |> printf "%s\n"
HelloEternalWorld
HelloEternalWorld
I try to understand why not?
All you're missing are parentheses, as it would compile if it were:
let rec HelloEternalWorld() =
Console.ReadLine() |> printf "%s\n"
HelloEternalWorld()
To define a function with no arguments you need the parentheses to distinguish the function from a simple value.
Please post the error messages you get, they say everything you need!
The value ... will be evaluated as part of its own definition.
Your code doesn't compile because you're declaring a recursive value (which doesn't exist) instead of a recursive function.
In order to make this a function, you'll have to write something like
let rec HelloEternalWorld() =
Console.ReadLine() |> printfn "%s"
HelloEternalWorld()
which is now a function of type unit -> unit.