Looking at the MSDN docs for Seq.nth and Seq.item, they appear to do exactly the same thing. Both have the same description... Computes the nth element in the collection
What's the difference? If there isn't one, why have both?
The reason why nth is deprecated is because the type signature for Seq.nth and List.nth is different, and so nth was deprecated in favor of item to avoid confusion. (Search for the word "nth" in that document to find the discussion). There was apparently also an Array.nth function at some point, but it no longer appears in the F# documentation on MSDN so I can't tell you what its signature was.
Signature for Seq.nth:
Seq.nth : int -> seq<'T> -> 'T
Signature for List.nth:
List.nth : 'T list -> int -> 'T
Note that the way List.nth is defined, you can't do someList |> List.nth 5. The Seq.nth takes its parameters in the correct order so that someSeq |> Seq.nth 5 is possible, but having these two functions take their parameters in a different order leads to confusion. To avoid this confusion, nth was deprecated and replaced by item, which has the same signature for lists, seqs, and arrays. (Yes, someArray |> Array.item 5 is possible, even though you'd usually just write that as someArray.[5]).
You can check the source code of these functions here: https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/seq.fs
[<CompiledName("Get")>]
let nth index (source : seq<'T>) = item index source
So they are the same.
Related
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).
Why have the data parameter in F# to come last, like the following code snippet shows:
let startsWith lookFor (s:string) = s.StartsWith(lookFor)
let str1 =
"hello"
|> startsWith "h"
I think part of your answer is in your question. The |> (forward pipe) operator lets you specify the last parameter to a function before you call it. If the parameters were in the opposite order, then that wouldn't work. The best examples of the power of this are with chaining of functions that operate on lists. Each function takes a list as its last parameter and returns a list that can be passed to the next function.
From http://www.tryfsharp.org/Learn/getting-started#chaining-functions:
[0..100]
|> List.filter (fun x -> x % 2 = 0)
|> List.map (fun x -> x * 2)
|> List.sum
The |> operator allows you to reorder your code by specifying the last
argument of a function before you call it. This example is
functionally equivalent to the previous code, but it reads much more
cleanly. First, it creates a list of numbers. Then, it pipes that list
of numbers to filter out the odds. Next, it pipes that result to
List.map to double it. Finally, it pipes the doubled numbers to
List.sum to add them together. The Forward Pipe Operator reorganizes
the function chain so that your code reads the way you think about the
problem instead of forcing you to think inside out.
As mentioned in the comments there is also the concept of currying, but I don't think that is as easy to grasp as chaining functions.
Is there a good reason for a different argument order in functions getting N-th element of Array, List or Seq:
Array.get source index
List .nth source index
Seq .nth index source
I would like to use pipe operator and it seems possible only with Seq:
s |> Seq.nth n
Is there a way to have the same notation with Array or List?
I don't think of any good reason to define Array.get and List.nth this way. Given that pipeplining is very common in F#, they should have been defined so that the source argument came last.
In case of List.nth, it doesn't change much because you can use Seq.nth and time complexity is still O(n) where n is length of the list:
[1..100] |> Seq.nth 10
It's not a good idea to use Seq.nth on arrays because you lose random access. To keep O(1) running time of Array.get, you can define:
[<RequireQualifiedAccess>]
module Array =
/// Get n-th element of an array in O(1) running time
let inline nth index source = Array.get source index
In general, different argument order can be alleviated by using flip function:
let inline flip f x y = f y x
You can use it directly on the functions above:
[1..100] |> flip List.nth 10
[|1..100|] |> flip Array.get 10
Just use backward pipe operator:
[1..1000] |> List.nth <| 42
Since both operators are left associative, x |> f <| y is parsed as (x |> f) <| y, and this does the trick.
Backward pipe operator is also useful if you want to remove parentheses: f (very long expression) can be replaced with f <| very long expression.
Since Pad and bytebuster answered your last question I will focus on the why part.
This is based my current knowledge and not historical facts.
Since F# derived from OCaml and OCaml has Array and List but not Seq and F# uses |> for natural pipelining and type checking and OCaml lacks the pipleline operator, the authors of F# made the switch for Seq. But obviously to be backward compatablie with OCaml they did not switch everything.
I have a list of type IList<Effort>. The model Effort contains a float called Amount. I would like to return the sum of Amount for the whole list, in F#. How would this be achieved?
efforts |> Seq.sumBy (fun e -> e.Amount)
Upvoted the answers of Seq.fold, pipelined Seq.fold, and pipelined Seq.sumBy (I like the third one best).
That said, no one has mentioned that seq<'T> is F#'s name for IEnumerable<T>, and so the Seq module functions work on any IEnumerable, including ILists.
Seq.fold (fun acc (effort: Effort) -> acc + effort.Amount) 0.0 efforts
One detail that may be interesting is that you can also avoid using type annotations. In the code by sepp2k, you need to specify that the effort value has a type Effort, because the compiler is processing code from the left to the right (and it would fail on the call effort.Amount if it didn't know the type). You can write this using pipelining operator:
efforts |> Seq.fold (fun acc effort -> acc + effort.Amount) 0.0
Now, the compiler knows the type of effort because it knows that it is processing a collection efforts of type IList<Effort>. It's a minor improvement, but I think it's quite nice.
A real F# noob question, but what is |> called and what does it do?
It's called the forward pipe operator. It pipes the result of one function to another.
The Forward pipe operator is simply defined as:
let (|>) x f = f x
And has a type signature:
'a -> ('a -> 'b) -> 'b
Which resolves to: given a generic type 'a, and a function which takes an 'a and returns a 'b, then return the application of the function on the input.
You can read more detail about how it works in an article here.
I usually refer to |> as the pipelining operator, but I'm not sure whether the official name is pipe operator or pipelining operator (though it probably doesn't really matter as the names are similar enough to avoid confusion :-)).
#LBushkin already gave a great answer, so I'll just add a couple of observations that may be also interesting. Obviously, the pipelining operator got it's name because it can be used for creating a pipeline that processes some data in several steps. The typical use is when working with lists:
[0 .. 10]
|> List.filter (fun n -> n % 3 = 0) // Get numbers divisible by three
|> List.map (fun n -> n * n) // Calculate squared of such numbers
This gives the result [0; 9; 36; 81]. Also, the operator is left-associative which means that the expression input |> f |> g is interpreted as (input |> f) |> g, which makes it possible to sequence multiple operations using |>.
Finally, I find it quite interesting that pipelining operaor in many cases corresponds to method chaining from object-oriented langauges. For example, the previous list processing example would look like this in C#:
Enumerable.Range(0, 10)
.Where(n => n % 3 == 0) // Get numbers divisible by three
.Select(n => n * n) // Calculate squared of such numbers
This may give you some idea about when the operator can be used if you're comming fromt the object-oriented background (although it is used in many other situations in F#).
As far as F# itself is concerned, the name is op_PipeRight (although no human would call it that). I pronounce it "pipe", like the unix shell pipe.
The spec is useful for figuring out these kinds of things. Section 4.1 has the operator names.
http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html
Don't forget to check out the library reference docs:
http://msdn.microsoft.com/en-us/library/ee353754(v=VS.100).aspx
which list the operators.