### Code Snippet:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

type 'a ListLazy = Cons of 'a * 'a ListLazy Lazy | Nil

module List =

module Lazy =

let single h = Cons(h, lazy (Nil))

let cons h l = Cons(h, lazy (l))

let head = function | Nil -> failwith "empty list" | Cons(h,_) -> h

let tail = function | Nil -> failwith "empty list" | Cons(_,t) -> t.Force()

let rec iter f = function

| Nil -> () | Cons(h,t) -> f h; iter f (t.Force())

let rec map f = function

| Nil -> Nil | Cons(h,t) -> Cons(f h, lazy (map f (t.Force())))

let rec fold f init = function

| Nil -> init | Cons(h,t) -> fold f (f init h) (t.Force())

let rec foldBack f init = function

| Nil -> init | Cons(h,t) -> f h (lazy (foldBack f init (t.Force())))

let rec unfold f init = f init |> function

| None -> Nil | Some(a,s) -> Cons (a, lazy (unfold f s))

let rec reduce f = function

| Nil -> failwith "empty list" | Cons(h,t) -> fold f h (t.Force())

let rec reduceBack f = function

| Nil -> failwith "empty list" | Cons(h,t) -> foldBack f h (t.Force())

let rec skip n = function

| Nil -> Nil | Cons(h,t) -> (n = 0I) |> function

| true -> cons h (t.Force())

| false -> skip (n-1I) (t.Force())

let rec take n = function

| Nil -> Nil | Cons(h,t) -> (n = 0I) |> function

| true -> Nil

| false -> Cons(h, lazy (take (n-1I) (t.Force())))

let rec append l1 l2 = l1 |> function

| Nil -> l2 | Cons(h,t) -> Cons(h, lazy (append (t.Force()) l2))

let rec concat = function

| Nil -> Nil | Cons(h,t) -> append h (concat (t.Force()))

let rec ofList = function

| [] -> Nil | h :: t -> cons h (ofList t)

let toList l =

let rec toList' acc = function

| Nil -> List.rev acc

| Cons(h,t) -> toList' (h::acc) (t.Force())

toList' [] l

### Code output:

### Infinite Fibonacci (and squared) sequence

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

let fib =

(List.Lazy.single 0I,

List.Lazy.unfold(fun (a1,a2) -> Some(a1+a2,(a2,a1+a2))) (1I,0I))

||> List.Lazy.append

let fibSquared =

fib |> List.Lazy.foldBack(fun x l -> Cons(x*x,l)) Nil

fib

|> List.Lazy.take 10I

|> List.Lazy.iter(printf "%A ")

fibSquared

|> List.Lazy.take 10I

|> List.Lazy.iter(printf "%A ")

### Runtime errors when skipping/taking on empty sequences (F# Seq)

1

2

3

4

5

6

fib

|> List.Lazy.take 10I

|> List.Lazy.toList

|> List.toSeq

|> Seq.skip 20

|> Seq.iter(printf "%A ")

1

2

3

4

5

6

fib

|> List.Lazy.take 10I

|> List.Lazy.toList

|> List.toSeq

|> Seq.take 20

|> Seq.iter(printf "%A ")

### No runtime errors when skipping/taking on empty lists

1

2

3

4

5

6

7

8

9

fib

|> List.Lazy.take 10I

|> List.Lazy.skip 20I // Behave as C# Linq.Enumerable.Skip

|> List.Lazy.iter(printf "%A ")

fib

|> List.Lazy.take 10I

|> List.Lazy.take 20I // Behave as C# Linq.Enumerable.Take (or F# Seq.truncate)

|> List.Lazy.iter(printf "%A ")

### References:

- Inspiration: Higher Order List Operations Across Languages