I'm new to F# and I've been struggling with this for a while. I have a two-dimensional array ([,]) and I want to get a sequence of all the elements in this array. While there seem to be options to iterate such an array (e.g. Array2D.iter), I want to pass the sequence to some other functions, not just iterate the elements.
In the end, I've worked around this with the following function:
let getAllElements (a: MyDiscriminatedUnionType[,]) : (seq<MyDiscriminatedUnionType>) =
seq { for x in a do yield (x :?> MyDiscriminatedUnionType) }
this seems to work but looks very excessive to me. Since the for .. in expression works on an enumerable-expression there already seems to be a way to enumerate a multidimensional array more easily?
Also I can't really figure out how to make this function more generic, so that this isn't tied to MyDiscriminatedUnionType but works with all multi-dimensional arrays.
To answer the second part of your question, you can make the function generic by replacing MyDiscriminatedUnionType type with a generic type parameter such as 'a:
let getAllElements (a:'a[,]) : seq<'a> =
seq { for x in a do yield x :?> 'a }
I think the code is quite clean - it would be nice if there was a built-in function for this (say, Array2D.toSeq) and I think it would be reasonable to suggest this as an addition to the standard F# library, but I don't think there is a function like this - and then the sequence expression is a nice way of writing this.
The only annoying thing is that you have to cast x using x :?> 'a. This is because the 2D array type does not implement a generic IEnumerable<'a> interface, but only the (old style) non-generic version.
You could avoid that by iterating over the indices and indexing into the array, which is a bit longer, but avoids the ugly casting:
let getAllElements (a:'a[,]) : seq<'a> =
seq { for i in 0 .. a.GetLength(0)-1 do
for j in 0 .. a.GetLength(1)-1 do yield a.[i,j] }
Related
with the following:
let a = "hello world".Split(' ')
the return type is a string array, but the type is written as:
System.String[]
I'm not understanding why:
you declare an array with [| ... |] but it is displayed as [ ... ] in the type
you declare a list with [ ... ] but it is displayed as x list in the type
Another example:
([| 3 |]).GetType()
val it : System.Type =
System.Int32[]
Why is it like this?
This is an inconsistency that is probably a result of the fact that F# is a .NET language.
In F#, you want lists more often than arrays, so it makes sense to use a shorter syntax [ ... ] for lists and longer syntax [| ... |] for arrays.
In .NET, array types are written as System.Int32[]. This is what you get from GetType and there is no way F# can override this, because it's coming from the .NET library.
As for the type names, you can always use 'a list and 'a array if you want to write types explicitly.
The most inconsistent features is the fact that you can write an array type such as int[] in F# too. I agree this is confusing. I think F# simply adopted the notation used in C# here. However, note that this also lets you define multi-dimensional arrays easily like int[,] and int[,,]. I don't think there is other syntax for multi-dimensional array types.
I think there are reasons for this, but they're not very satisfying:
Types and values are not written the same way. For example, a tuple type is written as 'A * 'B, while a tuple value is written (a, b). Some of us might've preferred ('A, 'B) for the type as well, but F# is actually consistent with how product types/values are represented mathematically.
Lists are more fundamental to functional programming than arrays, so it makes sense that fewer keystrokes are needed to write a list than to write an array.
F# inherited OCaml conventions, and adapted them to .NET, sometimes awkwardly. The type of [| 1; 2; 3 |] in OCaml is int array. F# accepts the .NET/C# name int[] as well, which is confusing, but you can still use the OCaml syntax in your code if you want: let arr : int array = Array.empty.
I'm learning F#. I'm here because I had something hard to understand about value restriction.
Here are the examples from the book I'm studying with.
let mapFirst = List.map fst
Since I had learned FP with haskell, I was pretty sure that this code would be well compiled, but it was not the case. It resulted error FS0030 (Sorry that I can't copy-paste fsi error message, since it was written in korean). Instead, I had to provide an explicit argument like:
let mapFirst inp = List.map fst inp // or inp |> List.map fst
But why? I thought that with the above example, compiler can surely infer the type of given value:
val mapFirst : ('a * 'b) list -> 'a list
If I remind correctly, I called this thing in haskell eta-conversion, and above two examples are entirely identical. (Maybe not entirely, though). Why should I privide parameters explicitly to the function can be curried without any loss of information?
I've understood that something like
let empties = Array.create 100 []
will not compile and why, but I don't think It has something to do with my question.
※ I took a look on this question, but it did not help.
This has to do with mutability.
Consider this snippet:
type T<'a> = { mutable x : 'a option }
let t = { x = None }
The type of t is T<'a> - that is, t is generic, it has a generic parameter 'a, meaning t.x can be of any type - whatever the consumer chooses.
Then, suppose in one part of the program you do:
t.x <- Some 42
Perfectly legitimate: when accessing t you choose 'a = int and then t.x : int option, so you can push Some 42 into it.
Then, suppose in another part of your program you do:
t.x <- Some "foo"
Oh noes, what happens now? Is t.x : int option or is it string option? If the compiler faithfully compiled your code, it would result in data corruption. So the compiler refuses, just in case.
Since in general the compiler can't really check if there is something mutable deep inside your type, it takes the safe route and rejects values (meaning "not functions") that are inferred to be generic.
Note that this applies to syntactic values, not logical ones. Even if your value is really a function, but isn't syntactically defined as such (i.e. lacks parameters), the value restriction still applies. As an illustration, consider this:
type T<'a> = { mutable x : 'a option }
let f t x =
t.x <- Some x
let g = f { x = None }
Here, even though g is really a function, the restriction works in exactly the same as with my first example above: every call to g tries to operate on the same generic value T<'a>
In some simpler cases the compiler can take a shortcut though. Thus, for example this line alone doesn't compile:
let f = List.map id
But these two lines do:
let f = List.map id
let x = f [1;2;3]
This is because the second line allows the compiler to infer that f : list int -> list int, so the generic parameter disappears, and everybody is happy.
In practice it turns out that this shortcut covers the vast majority of cases. The only time you really bump against the value restriction is when you try to export such generic value from the module.
In Haskell this whole situation doesn't happen, because Haskell doesn't admit mutation. Simple as that.
But then again, even though Haskell doesn't admit mutation, it kinda sorta does - via unsafePerformIO. And guess what - in that scenario you do risk bumping into the same problem. It's even mentioned in the documentation.
Except GHC doesn't refuse to compile it - after all, if you're using unsafePerformIO, you must know what you're doing. Right? :-)
Why does this statement give me a type mismatch error,
let x = List.rev [] in (3::x, true::x);;
while this statement does not?
let x = [] in (3::x, true::x);;
I'm assuming it is because x is given a function call in the first statement, while it is only give an empty list in the second statement. But, I am not sure exactly why the second works and the first does not? Any help will be much appreciated. Thanks!
Try the following:
let x = [] ;;
Result: val x : 'a list. F# knows that x is a list of as-yet unknown type. If it had any contents, its type would be known. This works perfectly well.
But the following will not work:
let x = List.rev [] ;;
Result:
error FS0030: Value restriction. The value 'x' has been inferred to have generic type
val x : '_a list
Either define 'x' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
The "value restriction" error in F# can be hard to understand — why is [] allowed when List.rev [] is not? — but this article goes into some details. Essentially, F# can always feel safe making functions generic, but it can only feel safe making values generic if the following two conditions apply:
The expression on the right-hand side of the let is a pure value, e.g. it has no side-effects,
and
The expression on the right-hand side of the let is immutable.
When the expression is [], then F# knows that it's a pure, immutable value, so it can make it generic ('a list). But when the expression is someFunction [], the F# compiler doesn't know what someFunction is going to do. Even though in this case, we know that List.rev is part of the standard library and matches those two scenarios, the F# compiler can't know that. In a completely pure language like Haskell, you can know from a function's type signature that it's pure, but F# is a more pragmatic language. So F# takes the guaranteed-safe approach and does not make the result of List.rev [] generic.
Therefore, when you write let x = [] in (3::x, true::x), the [] value is a generic empty list, so it can become either an int list or a bool list as needed. But when you write let x = List.rev [] in (3::x, true::x), F# cannot make List.rev [] generic. It can say "This is a list of a type I don't yet know", and wait for the type to become clear. Then the first expression of a specific type that uses this list, in this case 3::x, will "lock" the type of that list. I.e., F# cannot consider this list to be generic, so now it has figured out that this empty list is an empty list of ints. And then when you try to append a bool to an empty int list, that's an error.
If you flipped the tuple around so that it was true::x, 3::x then the type error would "flip" as well: it would expect a bool list and find an int list.
So the short version of this answer is: you're hitting the F# value restriction, even though that's not immediately obvious since the error you got didn't mention value restriction at all.
See Understanding F# Value Restriction Errors for a good discussion of the value restriction, including the most common place where you'd normally see it (partially-applied functions).
Is it possible to iterate through an array using pattering matching just like we do with lists in F#? I tried something like this:
type Alphabet = A | B
let rec calc (l: Alphabet []) = match l with
|l when l.[0] = A -> 5+(calc l.[1..])
|l when l.[0] = B -> 10+(calc l.[1..])
|l when l = [||] -> 0
calc [|A;A;B|]
The problem seems to be that the loop goes on and results a stackoverflow. Is it possible to do so?
I think you are trying to do this:
let toInteger = function
| A -> 5
| B -> 10
[|A; A; B|] |> Array.sumBy toInteger
In pattern matching, you can use an array pattern: for example, [|a; b; c|] matches against a three-element array. But there is no :: operator for arrays, so it's cumbersome to use an array the way you'd use a list. This is because you can't get the array's tail as a new array without copying it.
There are a number of issues with the question's code:
It crashes due to going out of bounds of the array. This is because you are not verifying that the .[1..] slice exists.
It is not tail recursive. This may be the reason you're seeing a stack overflow on long lists.
Two features are mixed into one function, making it complicated to read: the conversion to integer and the summation.
The compiler cannot verify that the pattern match covers all cases, so it issues a warning.
As hinted before, the copying of arrays is costly. This algorithm has O(n^2) in the length of the array, making it extremely expensive for long arrays. Unlike Array.sumBy or a tail-recursive function indexing into the array, which don't have to copy the array at all.
The heart of the issue here is the difference between arrays and singly linked immutable lists. Arrays are suited for iterating over them by increasing an index (which Array.sumBy does internally), while lists allow to treat their tail as an independent list without any copying (which List.sumBy does internally). It's usually best to use each data structure the way it is intended to be used.
I need a function like Seq.head, but returning None instead of throwing an exception when the sequence is empty, i.e., seq<'T> -> 'T option.
There are a jillion ways to do this. Here are several:
let items = Seq.init 10 id
let a = Seq.tryFind (fun _ -> true) items
let b = Seq.tryPick Some items
let c = if Seq.isEmpty items then None else Some (Seq.head items)
let d =
use e = items.GetEnumerator()
if e.MoveNext() then Some e.Current
else None
b is the one I use. Two questions:
Is there a particularly idiomatic way to do this?
Since there's no built-in Seq.tryHead function, does that indicate this shouldn't be necessary, is uncommon, or is better implemented without a function?
UPDATE
tryHead has been added to the standard library in F# 4.0.
I think (b) is probably the most idiomatic, for the same reason #Ramon gave.
I think the lack of Seq.tryHead just means that it is not super common.
I'm not sure, but my guess is that functional languages with Hindley-Milner type inference in general are sparse about implementing such specific functions on collection types because overloading isn't available and composing higher-order functions can be done tersely.
For example, C# Linq extensions are much more exhaustive than functions in F#'s Seq module (which itself is more exhaustive than functions on concrete collection types), and even has IEnumerable.FirstOrDefault. Practically every overload has a variation which performs a map.
I think emphasis on pattern matching and concrete types like list is also a reason.
Now, most of the above is speculation, but I think I may have a notion closer to being objective. I think a lot of the time tryPick and tryFind can be used in the first place instead of filter |> tryHead. For example, I find myself writing code like the following fairly frequently:
open System.Reflection
let ty = typeof<System.String> //suppose this type is actually unknown at compile time
seq {
for name in ["a";"b";"c"] do
yield ty.GetMethod(name)
} |> Seq.tryFind((<>)null)
instead of like
...
seq {
for name in ["a";"b";"c"] do
match ty.GetMethod(name) with
| null -> ()
| mi -> yield mi
} |> tryHead
You could define:
let seqTryHead s = Seq.tryPick Some s
It is of type seq<'a> -> 'a option. Note that I don't beta-reduce because of the generic value limitation.