Can someone clarify monads / computation expressions and their syntax, in F# - f#

First, I've read:
https://fsharpforfunandprofit.com/posts/elevated-world/
and
https://ericlippert.com/2013/02/21/monads-part-one/
I feel like I have all the pieces, but not the part that joins it all together, so I have several questions that can probably be answered all together.
Also, F# is the first time I'm confronted to monads / computation expressions. I come from a C background and have no experience with other functional languages and these concepts.
I would like to clarify the terminology: as far as I understand, monads are the model and computation expressions are the F# implementation of this model. Is that correct?
To that effect, I seem to understand that there are a few underlying functionalities (bind, map, etc) that are called that way when you declare an expression, but require a totally different syntax (let!, yield!, etc) when used. However, you can still use the original terms as wanted (Option.map, etc). This seems very confusing, so I'm curious if I got this right, and if so, why two syntax for the same thing?
As far as practical uses, it looks to me like the following:
You describe a model in which you wrap your data in whatever container you design and provide functions (like bind and map) to be able to chain container to container operations (like Result<int, _> -> Result<int, _>), or non container to containers operations (like int -> Result<int, _>), etc. Is that correct?
Then you build, within that context, an expression that uses that model in order to build an operation chain. Is this a correct assumption, or am I missing the big picture?
I am routinely using Result, Option, etc but I'm trying to get a good sense of the underlying mechanism.
As experiment, I took this from the web:
type ResultBuilder () =
member this.Bind(x, f) =
match x with
| Ok x -> f x
| Error e -> Error e
member this.Return x = Ok x
member this.ReturnFrom x = x
without truly understanding how Return / ReturnFrom are used, and successfully used it that way:
ResultBuilder() {
let! r1 = checkForEmptyGrid gridManager
let! r2 = checkValidation r1
let! r3 = checkMargin instrument marginAllowed lastTrade r2
return r3
}
and it definitely allowed to skip the hierarchical result match chain I would have needed otherwise.
But, yesterday I posted a kind of unrelated question: trying to extend the result type.. unsuccesfully, in F#
and user #Guran pointed out that Result.map could achieve the same thing.
so, I went to https://blog.jonathanchannon.com/2020-06-28-understanding-fsharp-map-and-bind/, took the code and made a Jupyter notebook out of it in order to play with it.
I came to understand that Map will take a non wrapped (inside Result) function and put the result in the wrapped/Result format and Bind will attach/bind functions which are already inside the Result model.
But somehow, despite the two links at the top going through the topic in depth, I don't seem to see the big picture, nor be able to visualize the different operations to wrap / unwrap operations, and their results in a custom model.

Ok, let's try this one more time. What could go wrong? :-)
Programming is more or less about capturing patterns. Well, at least the fun parts of it anyway. Look at the GoF "design patterns" for example. Yeah, I know, bad example :-/
Monad is a name given to this one particular pattern. This pattern became so incredibly useful that monads kind of gained a divine quality and everybody is in awe of them now. But really, it's just a pattern.
To see the pattern, let's take your example:
checkForEmptyGrid
checkValidation
checkMargin
First, every one of those functions may fail. To express that we make them return a Result<r, err> that can be either success or failure. So far so good. Now let's try to write the program:
let checkStuff gridManager instrument marginAllowed lastTrade =
let r1 = checkForEmptyGrid gridManager
match r1 with
| Error err -> Error err
| Ok r ->
let r2 = checkValidation r
match r2 with
| Error err -> Error err
| Ok r ->
let r3 = checkMargin instrument marginAllowed lastTrade r
match r3 with
| Error err -> Error err
| Ok r -> Ok r
See the pattern yet? See those three nearly identical nested blocks in there? At every step we do more or less the same thing: we're looking at the previous result, if it's an error, return that, and if not, we call the next function.
So let's try to extract that pattern for reuse. After all, that's what we do as programmers, isn't it?
let callNext result nextFunc =
match result with
| Error err -> Error err
| Ok r -> nextFunc r
Simple, right? Now we can rewrite the original code using this new function:
let checkStuff gridManager instrument marginAllowed lastTrade =
callNext (checkForEmptyGrid gridManager) (fun r1 ->
callNext (checkValidation r1) (fun r2 ->
callNext (checkMargin instrument marginAllowed lastTrade r2) (fun r3 ->
Ok r3
)
)
)
Oh, nice! How much shorter that is! The reason it's shorter is that our code now never deals with the Error case. That job was outsourced to callNext.
Now let's make it a bit prettier. First, if we flip callNext's parameters, we can use piping:
let callNext nextFunc result =
...
let checkStuff gridManager instrument marginAllowed lastTrade =
checkForEmptyGrid gridManager |> callNext (fun r1 ->
checkValidation r1 |> callNext (fun r2 ->
checkMargin instrument marginAllowed lastTrade r2 |> callNext (fun r3 ->
Ok r3
)
)
)
A bit fewer parens, but still a bit ugly. What if we made callNext an operator? Let's see if we can gain something:
let (>>=) result nextFunc =
...
let checkStuff gridManager instrument marginAllowed lastTrade =
checkForEmptyGrid gridManager >>= fun r1 ->
checkValidation r1 >>= fun r2 ->
checkMargin instrument marginAllowed lastTrade r2 >>= fun r3 ->
Ok r3
Oh nice! Now all the functions don't have to be in their very own parentheses - that's because operator syntax allows it.
But wait, we can do even better! Shift all the indentation to the left:
let checkStuff gridManager instrument marginAllowed lastTrade =
checkForEmptyGrid gridManager >>= fun r1 ->
checkValidation r1 >>= fun r2 ->
checkMargin instrument marginAllowed lastTrade r2 >>= fun r3 ->
Ok r3
Look: now it almost looks like we're "assigning" result of every call to a "variable", isn't that nice?
And there you go. You can just stop now and enjoy the >>= operator (which is called "bind" by the way ;-)
That's monad for you.
But wait! We're programmers, aren't we? Generalize all the things!
The code above works with Result<_,_>, but actually, Result itself is (almost) nowhere to be seen in the code. It might just as well be working with Option. Look!
let (>>=) opt f =
match opt with
| Some x -> f x
| None -> None
let checkStuff gridManager instrument marginAllowed lastTrade =
checkForEmptyGrid gridManager >>= fun r1 ->
checkValidation r1 >>= fun r2 ->
checkMargin instrument marginAllowed lastTrade r2 >>= fun r3 ->
Some r3
Can you spot the difference in checkStuff? The difference is just the little Some at the very end, which replaced the Ok that was there before. That's it!
But that's not all. This could also work with other things, besides Result and Option. You know JavaScript Promises? Those work too!
let checkStuff gridManager instrument marginAllowed lastTrade =
checkForEmptyGrid gridManager >>= fun r1 ->
checkValidation r1 >>= fun r2 ->
checkMargin instrument marginAllowed lastTrade r2 >>= fun r3 ->
new Promise(r3)
See the difference? It's at the very end again.
So it turns out, after you stare at this for a while, that this pattern of "gluing next function to the previous result" extends to a lot of things that are useful. Except this one little inconvenience: at the very end we have to use different methods of constructing the "ultimate return value" - Ok for Result, Some for Option, and whatever black magic Promises actually use, I don't remember.
But we can generalize that too! Why? Because it also has a pattern: it's a function that takes a value and returns the "wrapper" (Result, Option, Promise, or whatever) with that value inside:
let mkValue v = Ok v // For Result
let mkValue v = Some v // For Option
let mkValue v = new Promise(v) // For Promise
So really, in order to make our function-chaining code to work in different contexts, all we need to do is provide suitable definitions of >>= (usually called "bind") and mkValue (usually called "return", or in more modern Haskell - "pure", for complicated maths reasons).
And that's what a monad is: it's an implementation of those two things for a specific context. Why? In order to write down chaining computations in this convenient form rather than as a Ladder of Doom at the very top of this answer.
But wait, we're not done yet!
So useful monads turned out to be that functional languages decided it would be super nice to actually provide special syntax for them. The syntax is not magic, it just desugars to some bind and return calls in the end, but it makes the program look just a bit nicer.
The cleanest (in my opinion) job of this is done in Haskell (and its friend PureScript). It's called the "do notation", and here's how the code above would look in it:
checkStuff gridManager instrument marginAllowed lastTrade = do
r1 <- checkForEmptyGrid gridManager
r2 <- checkValidation r1
r3 <- checkMargin instrument marginAllowed lastTrade r2
return r3
The difference is that calls to >>= are "flipped" from right to left and use the special keyword <- (yes, that's a keyword, not an operator). Looks clean, doesn't it?
But F# doesn't use that style, it has its own. Partly this is due to the lack of type classes (so you have to provide a specific computation builder every time), and partly, I think, it's just trying to maintain the general aesthetic of the language. I'm not an F# designer, so I can't speak to the reasons exactly, but whatever they are, the equivalent syntax would be this:
let checkStuff gridManager instrument marginAllowed lastTrade = result {
let! r1 = checkForEmptyGrid gridManager
let! r2 = checkValidation r1
let! r3 = checkMargin instrument marginAllowed lastTrade r2
return r3
}
And the desugaring process is also a bit more involved than just inserting calls to >>=. Instead, every let! is replaced by a call to result.Bind and every return - by result.Return. And if you look at the implementations of those methods (you quoted them in your question), you'll see that they match exactly my implementations in this answer.
The difference is that Bind and Return are not in the operator form and they're methods on ResultBuilder, not standalone functions. This is required in F# because it doesn't have a general global overloading mechanism (such as type classes in Haskell). But otherwise the idea is the same.
Also, F# computation expressions are actually trying to be more than just an implementation of monads. They also have all this other stuff - for, yield, join, where, and you can even add your own keywords (with some limitations), etc. I'm not completely convinced this was the best design choice, but hey! They work very well, so who am I to complain?
And finally, on the subject of map. Map can be seen as just a special case of bind. You can implement it like this:
let map fn result = result >>= \r -> mkValue (fn r)
But usually map is seen as its own thing, not as bind's little brother. Why? Because it's actually applicable to more things than bind. Things that cannot be monads can still have map. I'm not going to expand on this here, it's a discussion for a whole other post. Just wanted to quickly mention it.

Related

How to write efficient list/seq functions in F#? (mapFoldWhile)

I was trying to write a generic mapFoldWhile function, which is just mapFold but requires the state to be an option and stops as soon as it encounters a None state.
I don't want to use mapFold because it will transform the entire list, but I want it to stop as soon as an invalid state (i.e. None) is found.
This was myfirst attempt:
let mapFoldWhile (f : 'State option -> 'T -> 'Result * 'State option) (state : 'State option) (list : 'T list) =
let rec mapRec f state list results =
match list with
| [] -> (List.rev results, state)
| item :: tail ->
let (result, newState) = f state item
match newState with
| Some x -> mapRec f newState tail (result :: results)
| None -> ([], None)
mapRec f state list []
The List.rev irked me, since the point of the exercise was to exit early and constructing a new list ought to be even slower.
So I looked up what F#'s very own map does, which was:
let map f list = Microsoft.FSharp.Primitives.Basics.List.map f list
The ominous Microsoft.FSharp.Primitives.Basics.List.map can be found here and looks like this:
let map f x =
match x with
| [] -> []
| [h] -> [f h]
| (h::t) ->
let cons = freshConsNoTail (f h)
mapToFreshConsTail cons f t
cons
The consNoTail stuff is also in this file:
// optimized mutation-based implementation. This code is only valid in fslib, where mutation of private
// tail cons cells is permitted in carefully written library code.
let inline setFreshConsTail cons t = cons.(::).1 <- t
let inline freshConsNoTail h = h :: (# "ldnull" : 'T list #)
So I guess it turns out that F#'s immutable lists are actually mutable because performance? I'm a bit worried about this, having used the prepend-then-reverse list approach as I thought it was the "way to go" in F#.
I'm not very experienced with F# or functional programming in general, so maybe (probably) the whole idea of creating a new mapFoldWhile function is the wrong thing to do, but then what am I to do instead?
I often find myself in situations where I need to "exit early" because a collection item is "invalid" and I know that I don't have to look at the rest. I'm using List.pick or Seq.takeWhile in some cases, but in other instances I need to do more (mapFold).
Is there an efficient solution to this kind of problem (mapFoldWhile in particular and "exit early" in general) with functional programming concepts, or do I have to switch to an imperative solution / use a Collections.Generics.List?
In most cases, using List.rev is a perfectly sufficient solution.
You are right that the F# core library uses mutation and other dirty hacks to squeeze some more performance out of the F# list operations, but I think the micro-optimizations done there are not particularly good example. F# list functions are used almost everywhere so it might be a good trade-off, but I would not follow it in most situations.
Running your function with the following:
let l = [ 1 .. 1000000 ]
#time
mapFoldWhile (fun s v -> 0, s) (Some 1) l
I get ~240ms on the second line when I run the function without changes. When I just drop List.rev (so that it returns the data in the other order), I get around ~190ms. If you are really calling the function frequently enough that this matters, then you'd have to use mutation (actually, your own mutable list type), but I think that is rarely worth it.
For general "exit early" problems, you can often write the code as a composition of Seq.scan and Seq.takeWhile. For example, say you want to sum numbers from a sequence until you reach 1000. You can write:
input
|> Seq.scan (fun sum v -> v + sum) 0
|> Seq.takeWhile (fun sum -> sum < 1000)
Using Seq.scan generates a sequence of sums that is over the whole input, but since this is lazily generated, using Seq.takeWhile stops the computation as soon as the exit condition happens.

Matching Patterns of Objects in F#

I have zero experience with F#. I started reading F# for C# Developers this weekend.
I had a problem recently (C# Code) where I had to search a list of .NET objects for subsets of objects that matched a certain pattern.
I described it as "regex style matching for objects" in the question. And I did get a great solution that I was happy with, and which seems to perform quite well.
But my recent interest in F# lead me to wonder whether functional programming might have an even better solution.
How would you solve this problem in F#?
Regex Style Pattern Matching in .NET Object Lists
One interesting functional concept that might be useful here is parser combinators. The idea is that you use composable functions that describe how to read some input and then compose parsers for complex patterns from a couple of primitives.
Parsers normally work over strings, but there is no reason why you couldn't use the same method to read a sequence of chromosomes.
With parser combinators, you would rewrite the "regex" as a composition of F# functions. Something like:
sequence [
zeroOrMore (chromosomeType R)
repeat 3 (chromosomeType B)
zeroOrMore (chromosomeType D) ]
This would give you a function that takes a list of chromosome objects and returns the parsed result - the subset of the list. The idea is that functions like zeroOrMore build parsers that detect certain patterns and you compose functions to build a parser - you get a function that you can just run on the input to parse it.
Explaining parser combinators is a bit too long for a SO answer, but it would probably be the most idiomatic F# approach to solving the problem.
This is a comment posted as an answer because it is to long for a comment.
Since it seems that Regular Expressions are working for your problem and that you might suspect that F# pattern matching or active patterns might be a better solution I will add some understanding.
The input R+B{3}D+ as I see it is a formal grammar, and as such will require a parser and evaluation engine, or the creation of something like a finite state machine. Since you know already that .Net Regex can solve this problem, why go through all of the trouble to recreate this with F#. Even using F# pattern matching and active patterns will not be easier than using RegEx.
Thus the problem is basically to convert the C# code to F# code and make use of RegEx. So you are asking us to translate your C# to F# and that is not a valid SO question.
EDIT
As Mark Seemann noted in a comment the only input we have is R+B{3}D+. So if your actual grammar is more complicated than what RegEx can handle then there might be a better solution in F#.
Hopefully this helps you understand what you are asking.
Building on the other answers: Start by implementing a parser combinator allowing composition of the type Parser<'a list>. Add parsers for the minimal grammar required by R+B{3}D+.
type Result<'T> = Success of 'T | Failure
type Parser<'T> = Parser of ('T -> Result<'T * 'T>)
module ListParser =
let (.>>.) (Parser f1) (Parser f2) =
Parser <| fun input ->
match f1 input with
| Failure -> Failure
| Success(value1, rest1) ->
match f2 rest1 with
| Failure -> Failure
| Success(value2, rest2) ->
Success(value1 # value2, rest2)
let oneOrMore what =
let rec aux gotOne acc = function
| x::xs when what = x -> aux true (x::acc) xs
| xss when gotOne -> Success(List.rev acc, xss)
| _ -> Failure
Parser <| aux false []
let exactly what n =
let rec aux i acc = function
| xss when i = 0 -> Success(List.rev acc, xss)
| x::xs when what = x -> aux (i - 1) (x::acc) xs
| _ -> Failure
Parser <| aux n []
Finally create a function which will run the parser repeatedly until the input list is exhausted.
open ListParser
let runForall (Parser f) xss =
let rec aux n acc xss =
match xss, f xss with
| [], _ -> List.rev acc
| _::xs, Failure -> aux (n + 1) acc xs
| _, Success(value, rest) ->
aux (n + List.length value) ((n + 1, value)::acc) rest
aux 0 [] xss
type ChromosomeType = R | B | D
[D;R;R;B;B;B;D;D;B;R;R;B;B;B;D;D;R;R;B;B;B;D;D]
|> runForall (oneOrMore R .>>. exactly B 3 .>>. oneOrMore D)
// val it : (int * ChromosomeType list) list =
// [(2, [R; R; B; B; B; D; D]); (10, [R; R; B; B; B; D; D]);
// (17, [R; R; B; B; B; D; D])]

F# tail call optimization issues on Mono

I have an issues concerning the F# on mono. Im doing this course in functional programming at my university. In the course we are using F#, and I uses Xamarin as my editor.
The thing is that we had a lesson on tail recursion, as a tool for getting efficiency. But when you are not able to write your function tail recursive, we had to use continuous, such that we using the heap and not the stack.
This seems not to work on mono 3.10.0 with F# 3.1, I get an System.StackOverflowException. This should be impossible to get, due the continuous should use the heap.
let rec fibC n c =
match n with
|0 -> c 0
|1 -> c 1
|n -> fibC (n-1) (fun v1 -> fibC (n-2) (fun v2 -> c(v1+v2)))
I tested a Fibonacci implementation passing an accumulator instead of a function (continuation) like this:
let fib n =
let rec _fib i (a,b) =
match i with
| 0 -> a
| _ -> _fib (i-1) (b, a+b)
_fib n (0,1)
which worked fine on Mono, i.e. no stack overflow.
So I guess it's only an issue with TCO when using continuations. There's a Xamarin ticket from June 2013 addressing this.

Pairwise Sequence Processing to compare db tables

Consider the following Use case:
I want to iterate through 2 db tables in parallel and find differences and gaps/missing records in either table. Assume that 1) pk of table is an Int ID field; 2) the tables are read in ID order; 3) records may be missing from either table (with corresponding sequence gaps).
I'd like to do this in a single pass over each db - using lazy reads. (My initial version of this program uses sequence objects and the data reader - unfortunately makes multiple passes over each db).
I've thought of using pairwise sequence processing and use Seq.skip within the iterations to try and keep the table processing in sync. However apparently this is very slow as I Seq.skip has a high overhead (creating new sequences under the hood) so this could be a problem with a large table (say 200k recs).
I imagine this is a common design pattern (compare concurrent data streams from different sources) and am interested in feedback/comments/links to similar projects.
Anyone care to comment?
Here's my (completely untested) take, doing a single pass over both tables:
let findDifferences readerA readerB =
let idsA, idsB =
let getIds (reader:System.Data.Common.DbDataReader) =
reader |> LazyList.unfold (fun reader ->
if reader.Read ()
then Some (reader.GetInt32 0, reader)
else None)
getIds readerA, getIds readerB
let onlyInA, onlyInB = ResizeArray<_>(), ResizeArray<_>()
let rec impl a b =
let inline handleOnlyInA idA as' = onlyInA.Add idA; impl as' b
let inline handleOnlyInB idB bs' = onlyInB.Add idB; impl a bs'
match a, b with
| LazyList.Cons (idA, as'), LazyList.Cons (idB, bs') ->
if idA < idB then handleOnlyInA idA as'
elif idA > idB then handleOnlyInB idB bs'
else impl as' bs'
| LazyList.Nil, LazyList.Nil -> () // termination condition
| LazyList.Cons (idA, as'), _ -> handleOnlyInA idA as'
| _, LazyList.Cons (idB, bs') -> handleOnlyInB idB bs'
impl idsA idsB
onlyInA.ToArray (), onlyInB.ToArray ()
This takes two DataReaders (one for each table) and returns two int[]s which indicate the IDs that were only present in their respective table. The code assumes that the ID field is of type int and is at ordinal index 0.
Also note that this code uses LazyList from the F# PowerPack, so you'll need to get that if you don't already have it. If you're targeting .NET 4.0 then I strongly recommend getting the .NET 4.0 binaries which I've built and hosted here, as the binaries from the F# PowerPack site only target .NET 2.0 and sometimes don't play nice with VS2010 SP1 (see this thread for more info: Problem with F# Powerpack. Method not found error).
When you use sequences, any lazy function adds some overhead on the sequence. Calling Seq.skip thousands of times on the same sequence will clearly be slow.
You can use Seq.zip or Seq.map2 to process two sequences at a time:
> Seq.map2 (+) [1..3] [10..12];;
val it : seq<int> = seq [11; 13; 15]
If the Seq module is not enough, you might need to write your own function.
I'm not sure if I understand what you try to do, but this sample function might help you:
let fct (s1: seq<_>) (s2: seq<_>) =
use e1 = s1.GetEnumerator()
use e2 = s2.GetEnumerator()
let rec walk () =
// do some stuff with the element of both sequences
printfn "%d %d" e1.Current e2.Current
if cond1 then // move in both sequences
if e1.MoveNext() && e2.MoveNext() then walk ()
else () // end of a sequence
elif cond2 then // move to the next element of s1
if e1.MoveNext() then walk()
else () // end of s1
elif cond3 then // move to the next element of s2
if e2.MoveNext() then walk ()
else () // end of s2
// we need at least one element in each sequence
if e1.MoveNext() && e2.MoveNext() then walk()
Edit :
The previous function was meant to extend functionality of the Seq module, and you'll probably want to make it a high-order function. As ildjarn said, using LazyList can lead to cleaner code:
let rec merge (l1: LazyList<_>) (l2: LazyList<_>) =
match l1, l2 with
| LazyList.Cons(h1, t1), LazyList.Cons(h2, t2) ->
if h1 <= h2 then LazyList.cons h1 (merge t1 l2)
else LazyList.cons h2 (merge l1 t2)
| LazyList.Nil, l2 -> l2
| _ -> l1
merge (LazyList.ofSeq [1; 4; 5; 7]) (LazyList.ofSeq [1; 2; 3; 6; 8; 9])
But I still think you should separate the iteration of your data, from the processing. Writing a high-order function to iterate is a good idea (at the end, it's not annoying if the iterator function code uses mutable enumerators).

Return item at position x in a list

I was reading this post While or Tail Recursion in F#, what to use when? were several people say that the 'functional way' of doing things is by using maps/folds and higher order functions instead of recursing and looping.
I have this function that returns the item at position x in a list:
let rec getPos l c = if c = 0 then List.head l else getPos (List.tail l) (c - 1)
how can it be converted to be more functional?
This is a primitive list function (also known as List.nth).
It is okay to use recursion, especially when creating the basic building blocks. Although it would be nicer with pattern matching instead of if-else, like this:
let rec getPos l c =
match l with
| h::_ when c = 0 -> h
| _::t -> getPos t (c-1)
| [] -> failwith "list too short"
It is possible to express this function with List.fold, however the result is less clear than the recursive version.
I'm not sure what you mean by more functional.
Are you rolling this yourself as a learning exercise?
If not, you could just try this:
> let mylist = [1;2;3;4];;
> let n = 2;;
> mylist.[n];;
Your definition is already pretty functional since it uses a tail-recursive function instead of an imperative loop construct. However, it also looks like something a Scheme programmer might have written because you're using head and tail.
I suspect you're really asking how to write it in a more idiomatic ML style. The answer is to use pattern matching:
let rec getPos list n =
match list with
| hd::tl ->
if n = 0 then hd
else getPos tl (n - 1)
| [] -> failWith "Index out of range."
The recursion on the structure of the list is now revealed in the code. You also get a warning if the pattern matching is non-exhaustive so you're forced to deal with the index too big error.
You're right that functional programming also encourages the use of combinators like map or fold (so called points-free style). But too much of it just leads to unreadable code. I don't think it's warranted in this case.
Of course, Benjol is right, in practice you would just write mylist.[n].
If you'd like to use high-order functions for this, you could do:
let nth n = Seq.take (n+1) >> Seq.fold (fun _ x -> Some x) None
let nth n = Seq.take (n+1) >> Seq.reduce (fun _ x -> x)
But the idea is really to have basic constructions and combine them build whatever you want. Getting the nth element of a sequence is clearly a basic block that you should use. If you want the nth item, as Benjol mentioned, do myList.[n].
For building basic constructions, there's nothing wrong to use recursion or mutable loops (and often, you have to do it this way).
Not as a practical solution, but as an exercise, here is one of the ways to express nth via foldr or, in F# terms, List.foldBack:
let myNth n xs =
let step e f = function |0 -> e |n -> f (n-1)
let error _ = failwith "List is too short"
List.foldBack step xs error n

Resources