ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

F# Computation Expression: Custom List Builder

F#

Goal -- WPM

Ready
Exercise Algorithm Area
1(*@
2A custom computation expression builder for constructing lists.
3This allows for more declarative list building using `yield`.
4*@)
5type ListBuilder() =
6member this.Yield(x) = [x]
7
8member this.YieldFrom(ys: list<'T>) = ys
9
10member this.Combine(xs: list<'T>, ys: list<'T>) = xs @ ys
11
12member this.Bind(xs: list<'T>, f: 'T -> list<'U>) : list<'U> =
13let mutable result = []
14for x in xs do
15let ys = f x
16result <- result @ ys
17result
18
19member this.Return(x) = [x]
20
21// For monadic bind with a function that returns a list
22member this.Delay(f: unit -> list<'T>) : list<'T> = f()
23
24// For monadic return with a value that is already a list
25member this.ReturnFrom(xs: list<'T>) = xs
26
27(*@
28Helper function to demonstrate the ListBuilder.
29*@)
30let buildListWithBuilder (builder: ListBuilder) =
31builder {
32yield 1
33yield! [2; 3]
34yield! builder {
35yield 4
36yield 5
37}
38yield! [6]
39}
40
41(*@
42Another example demonstrating `Bind` implicitly.
43*@)
44let buildListWithBind (builder: ListBuilder) =
45builder {
46for i in [1; 2] do
47yield! builder {
48yield i * 10
49yield i * 10 + 1
50}
51}
52
53(*@
54Example of using the builder with a function that returns a list.
55*@)
56let processNumbers (builder: ListBuilder) =
57let numbers = [1; 2; 3]
58builder {
59yield! builder {
60for n in numbers do
61yield n
62}
63yield! builder {
64for n in numbers do
65yield n * 10
66}
67}
68
69(*@
70The ListBuilder itself.
71*@)
72let listBuilder = ListBuilder()
73
74(*@
75Example of a more complex list construction.
76*@)
77let complexList (builder: ListBuilder) =
78builder {
79yield 1
80yield! [2; 3]
81let subList = builder {
82yield 4
83yield 5
84}
85yield! subList
86yield! [6]
87}
88
89(*@
90Demonstrates `ReturnFrom`.
91*@)
92let returnFromExample (builder: ListBuilder) =
93let preBuiltList = [10; 20]
94builder {
95yield 1
96yield! preBuiltList
97yield 2
98}
99
100(*@
101Demonstrates `Delay`.
102*@)
103let delayExample (builder: ListBuilder) =
104builder {
105yield! builder {
106yield 1
107yield 2
108}
109yield! builder {
110yield 3
111yield 4
112}
113}
114
115(*@
116A simple list builder for demonstration.
117*@)
118let simpleListBuilder = ListBuilder()
119
120(*@
121Final example of list construction.
122*@)
123let finalListConstruction (builder: ListBuilder) =
124builder {
125yield 100
126yield! [200; 300]
127}
Algorithm description viewbox

F# Computation Expression: Custom List Builder

Algorithm description:

This F# code defines a custom computation expression builder named `ListBuilder`. This builder allows developers to construct lists in a more declarative and readable way using the `yield` keyword, similar to how one might build collections in other languages. It demonstrates the core methods required for a computation expression, such as `Yield`, `YieldFrom`, `Combine`, `Bind`, and `Return`, enabling complex list manipulations and nested structures.

Algorithm explanation:

The `ListBuilder` implements the necessary methods for a computation expression to construct lists. `Yield` adds a single element, `YieldFrom` adds all elements from another list, and `Combine` concatenates two lists. The `Bind` method is crucial for chaining operations where a function returns a list; it iterates through the input list, applies the function to each element, and concatenates the resulting lists. `Return` creates a list with a single element. `Delay` and `ReturnFrom` are also implemented for monadic operations. The time complexity for building a list of N elements using `yield` and `yield!` is roughly O(N) due to list concatenation, assuming `Combine` is O(length of first list). The space complexity is O(N) to store the resulting list. Edge cases include empty input lists and deeply nested builder expressions. The builder works by composing the results of these methods, effectively transforming the computation expression syntax into standard F# list operations.

Pseudocode:

class ListBuilder:
  method Yield(element):
    return a list containing only element

  method YieldFrom(list):
    return the given list

  method Combine(list1, list2):
    return concatenation of list1 and list2

  method Bind(list, function):
    initialize empty result list
    for each element in list:
      apply function to element to get sublist
      append sublist to result list
    return result list

  method Return(element):
    return a list containing only element

  method Delay(function):
    return the result of calling function()

  method ReturnFrom(list):
    return the given list