I'm very new to F# so please excuse the completely newbie question:
I have a sequence stored in a variable called prices. I'd like to output the contents of this sequence to the interactive window. What's the easiest command to do this?
Here is my sequence:
> prices;;
val it : seq<System.DateTime * float> = seq []
I've tried printf'ing it but that gives me the error:
> printf("%A", prices);;
printf("%A", prices);;
-------^^^^^^^^^^^^
stdin(82,8): error FS0001: The type ''b * 'c' is not compatible with the type 'Printf.TextWriterFormat<'a>'
Any help would be appreciated.
printf does not take parentheses:
printfn "%A" prices;;
(See F# function types: fun with tuples and currying for details)
You might also convert the seq to a list, e.g.
printfn "%A" (Seq.toList prices);;
Also, you can control interactive session printer capabilities by changing fsi.* properties
(FloatingPointFormat, PrintWidth, PrintDepth, PrintLength, ...)
F.e. please see: http://cs.hubfs.net/forums/post/7438.aspx
> prices;;
val it : seq<System.DateTime * float> = seq []
It's doing its job: seq [] means the sequence is empty.
Related
Why does printf output Some x for Some x, but <null> for None?
> printfn "%A" (Some 123);;
Some 123
val it : unit = ()
> printfn "%A" None;;
<null>
val it : unit = ()
In compiled code, F# uses the null value to represent the None case of option<'T> for efficiency. You can actually use the same for your own discriminated unions by using the CompilationRepresentationFlags. UseNullAsTrueValue compilation flag (see MSDN documentation).
You can see that this is what's going on by using the Object.ReferenceEquals method:
> let n = None;;
val n : 'a option
> System.Object.ReferenceEquals(n, null);;
val it : bool = true
Why does printfn "%A" just print the internal representation rather than recognizing that this actually represents the None case?
I think the answer is that printing is done dynamically using reflection and so the argument is just converted to a value of type obj at some point. Once you have a value null of type obj, it is not possible to recover what type it was before casting and so you cannot find out that null actually represents None (because null.GetType() fails). Presumably, the printing could use the static type information to get type information that way - but that would probably be more tricky to implement.
This is actually older behavior that won't go away. Tomas' answer is correct for older FSI, but if you install something newer (like .NET Core 3.1 latest, or .NET 5 preview) you'll see with dotnet fsi that None formats as None with your example.
*I edited my original post to include more info.
I'm working on an F# assignment where I'm supposed to create a function that takes an "any list list" as input and outputs an "any list". It should be able to concatenate a list of lists into a single list.
Here's what my function looks like:
let llst = [ [1] ; [2;3] ; ['d';'e';'f'] ]
let concat (llst:'a list list) : 'a list =
List.concat llst
List.iter (fun elem -> printf "%d " elem) concat
This solution more or less copied directly from microsofts example of using the List.concat function, the only exception being the specification of input/output types.
When i run the code i get this error:
concat.fsx(7,43): error FS0001: This expression was expected to have type
''a list'
but here has type
''b list list -> 'b list'
So it appears that concat is turning my llst into a character list, which i don't understand.
Can anyone help me understand why I'm getting this type error and how I can write a function that takes the types that I need?
The problem is somewhere in your implementation of the concat function. It is hard to say where exactly without seeing your code, but since this is an assignment, it is actually perhaps better to explain what the error message is telling you, so that you can find the issue yourself.
The error message is telling you that the F# type inference algorithm found a place in your code where the actual type of what you wrote does not match the type that is expected in that location. It also tells you what the two mismatching types are. For example, say you write something like this:
let concat (llst:'a list list) : 'a list =
llst
You will get the error you are getting on the second line, because the type of llst is 'a list list (the compiler knows this from the type annotation you give on line 1), but the expected type is the same as the result type of the function which is 'a list - also specified by your type annotation.
So, to help you find the issue - look at the exact place where you are getting an error and try to infer why compiler thinks that the actual type is 'a list list and try to understand why it expects 'a list as the type that should be in this place.
This is correct:
let concat (llst:'a list list) : 'a list =
List.concat llst
However, it's really equivalent to let concat = List.concat
This, however, doesn't compile, the elements of the lists need to be of the same type:
let llst = [ [1] ; [2;3] ; ['d';'e';'f'] ]
This also is problematic:
List.iter (fun elem -> printf "%d " elem) concat
List.iter has two arguments and the second one needs to be a List. However in your case you are (as per compiler error) providing your concat function which is a a' List List -> a' List.
What I suspect you meant to do, is apply the concat function to your llist first:
List.iter (fun elem -> printf "%d " elem) (concat llist)
// or
llist
|> concat
|> List.iter (fun elem -> printf "%d " elem)
However, all of this is perhaps missing the point of the exercise. What perhaps you need to do is implement some simple recursion based on the empty / non-empty state of your list, ie. fill in the blanks from here:
let rec myconcat acc inlist =
match inlist with
| [] -> ??
| elt :: tail -> ??
In F# / Excel-Dna, what is the idiomatic way to rewrite the following function for a vector of strings? (i.e. a function which sorts a "vector" (=1d Excel range) of strings).
[<ExcelFunction(Category="Some Cat", Description="Sort 1d range filled with doubles.")>]
let mySortDouble (vect : double[]) : double[] =
Array.sort vect
If I merely replace the double types with string types in the above snippet, I get this error message : Initialization [Error] Method not registered - unsupported signature, abstract or generic: 'MyFSFunctions.mySortString'
I saw this previous question where Govert suggests to use the "Registration extensions" but I have not found how to use it to answer my current question.
As you have mySortDouble written, it won't even compile, because it returns a double[], not a double.
Here's an example that works, with some minimal error handling added.
[<ExcelFunction(Category="Some Cat", Description="Sort 1D range of strings.")>]
let SortStrings (vect : obj[]) =
try
vect
|> Seq.cast<string>
|> Seq.sort
|> Seq.toArray
|> box
with
| ex -> box ExcelError.ExcelErrorNA
For Registration samples
ParameterConversionConfiguration()
.AddReturnConversion(fun (values: double[]) ->
Array.map (string >> box) values
)
My attempt to do this is here (forgive the for loop - I was just curious to see if this was possible):
let (|>>) a (b : ('a -> unit) list) =
for x in b do
x a
but when I try to use it I get the error
That None of the types error message can occur if the function you're trying to use is defined further down the file or isn't imported correctly. Otherwise, your function definition seems ok.
I would discourage the use of a custom operator for this. I think they should be used very rarely. This one doesn't seem general enough to be worth defining and could make code hard to read. Here is one alternative:
[ printf "%A"; printfn "%A" ] |> List.iter ((|>) 1)
But it's even clearer and shorter to write out your operator definition inline:
for f in [ printf "%A"; printfn "%A" ] do f 1
I have tried MSDN's example for the Seq.choose function (written below) in both a .fsx file and the interactive window for Visual Studio, but it repeatedly returns an error FS0001, stating that the "None" option is a PageExt type rather than the abstract option type 'a option.
I have searched in vain for an explanation of the PageExt type or why this could be returning an error when the None keyword should just represent the "no value" option in the match expression.
let numbers = seq {1..20}
let evens = Seq.choose(fun x ->
match x with
| x when x%2=0 -> Some(x)
| _ -> None ) numbers
printfn "numbers = %A\n" numbers
printfn "evens = %A" evens
;;
| _ -> None ) numbers
---------------------------------------^^^^
>
C:Path\stdin(38,40): error FS0001: This expression was expected to have type
'a option
but here has type
PageExt
Thanks for any help anyone can offer!
The PageExt type is likely something that you've pulled into your current FSI session previously which bound something to None, essentially blocking FSI from recognizing the normal option types.
In F#, you can reuse names, which "shadows" the original value. For example, in FSI, if you type:
let a = 1;;
let a = 2.3;;
a;;
You'll notice that it shows:
val a : int = 1
Then
val a : float = 2.3
Finally
val it : float = 2.3
This isn't changing the definition of a, but rather defining a new a name that shadows (or "hides") the original bound value.
In your case, you have a None name that's bound to something with a PageExt type that's shadowing Option.None, preventing it from being usable.
The easiest way to fix this is to reset your FSI session. Right click in the F# Interactive window, and choose "Reset iteractive session". If you do that, then run the code you pasted, it will work fine.