Skip to content

Latest commit

 

History

History
204 lines (138 loc) · 5.75 KB

option.md

File metadata and controls

204 lines (138 loc) · 5.75 KB

Option

The goal is to implement the type Option<T>. It represents a a value of type T that is "optional" (might not exist).
Option has two variants.

  • Some for the case the value exist. Containing "some" value of type T.
  • None for the case the value doesn't exist.

Your solution should go here. There are also unit tests and sample solutions.

Option.some and Option.none

Create two free functions

  • Option.some taking any value and returning an Option instance holding that value. The returned value should have a value field containing the passed value and a hasValue field set to true.
  • Option.none taking no argument and returning an Option instance holding no value. The returned value should have a hasValue field set to false.
Hint 1

Define two different classes, one for each variant.

Hint 2

Define the Option type as the union of both variants.

Hint 3

Build the variants in such a way that Option becomes a discriminated union.

Hint 4

Ensure that the field hasValue has the type true in the Some class and the type false in the None class.

Hint 5
some<T>(t: T): Option<T>
none<T>(): Option<T>

Challenge: implement the None variant as a singleton without casting i.e. always the same instance is returned, regardless of the type the wrapped value has.

Challenge hint 1

Take a look at the never type in typescript.

Option.fromNullable

Write a free function that takes a value that might be null or undefined. If the value was null | undefined than None is returned, otherwise the value is wrapped in a Some. The return type should reflect that the Option can't contain null | undefined.

Hint 1

Typescript has a built in utility type NonNullable.

Hint 2
fromNullable<T>(nullishValue: T): Option<NonNullable<T>>

option.unwrapOr

Write a method unwrapOr that takes a default value that is returned if option is None. If option is Some the wrapped is value simply returned. unwrapOr should allow for widening the type. Meaning the type of the default value can differ from the wrapped type.

Hint 1

unwrapOr must introduce e new type for the Default value.

Hint 2

The return type is the union of the wrapped type and the type of the default value.

Hint 3
unwrapOr<U>(defaultValue: U): T | U

option.map

Write a method map that takes a function mapper and uses it to transform the wrapped value of the Option.

Hint 1

If the Option is None then map does nothing.

Hint 2

If the Option is Some then map calls the mapper function with the value of the option and returns the resulting value wrapped in a new Some.

Hint 3

map must introduce a new type. The mapper function takes a value of the wrapped type of the Option and returns the new type.

Hint 4
map<U>(mapper: (value:T) => U): Option<U>

option.flatMap

Write a method flatMap that takes a function mapper and uses it to transform the wrapped value. The mapper function should return an Option instance but the returned value of flatMap shall be flat i.e. not be a nested Option.

Hint 1

If the Option is None then flatMap does nothing.

Hint 2

If the Option is Some then flatMap calls the mapper function with the value of the option and returns the result.

Hint 3

flatMap must introduce a new type. The mapper function takes a value of the wrapped type of the Option and returns an Option of the new type.

Hint 4
flatMap<U>(mapper: (value:T) => Option<U>): Option<U>

Option.flatten

Write a free function flatten that takes an Option containing an Option and flattens it i.e. returns the nested Option.

Hint 1

If the Option is None then Option.flatten does nothing.

Hint 2

If the Option is Some then Option.flatten simply returns the wrapped value.

Hint 3

Option.flatten must introduce a new type that describes the value wrapped by two Options.

Hint 4
flatten<T>(option: Option<Option<T>>): Option<T>

Challenge 1: Implement flatten only using flatMap.

Challenge hint 1.1

flatMap already has a "flattening" behavior. Let the flatMap do nothing.

Challenge 2: Also implement a method named flatten that does the same. option.flatten should only be callable if option is known to contain another Option.

Challenge hint 2.1

Take a look at this parameters. They allow you to specify in which context a method is allowed to be called.