diff --git a/src/exo3/exo3.ts b/src/exo3/exo3.ts index 3b97f2e..906da02 100644 --- a/src/exo3/exo3.ts +++ b/src/exo3/exo3.ts @@ -5,10 +5,36 @@ import * as Option from 'fp-ts/lib/Option'; import { unimplemented } from '../utils'; +// Have you ever looked at the methods provided by `fp-ts` own `Array` and +// `ReadonlyArray` modules? They expose a load of functions to manipulate +// those collections. +// +// Some of those you likely are already familiar with, like `map` or `filter`. +// The difference with JavaScript's native `Array.prototype` methods is that +// these are more `fp-ts` friendly. +// +// In the following exercice, we will take a look at `Array.sort`. Contrary to +// its JavaScript counterpart, `fp-ts` sort takes as an argument something of +// type `Ord` where `T` is the type of elements contained in the collection. +// +// You can think as `Ord` as "something which describes how to order `T`s". + /////////////////////////////////////////////////////////////////////////////// // SORT PRIMITIVE TYPES // /////////////////////////////////////////////////////////////////////////////// +// The next two functions only take an array of values of a primitive JS type +// like `string` or `number` and return a new array with those values but +// sorted. +// +// Obviously, we want to call `ReadonlyArray.sort` (the `fp-ts` version! no +// cheating). But, contrary to `ReadonlyArray.prototype.sort` which takes an +// ordering function, this sort will only accept an `Ord`. +// +// HINT: The `Ord` module from `fp-ts` exposes some preconstructed instances +// of `Ord` for a few primitive `T`s such as `ordString: Ord` or +// `ordNumber: Ord`. + export const sortStrings: ( strings: ReadonlyArray, ) => ReadonlyArray = unimplemented; @@ -21,6 +47,14 @@ export const sortNumbers: ( // REVERSE SORT // /////////////////////////////////////////////////////////////////////////////// +// This next function will sort an array of numbers but in descending order +// (which unfortunately is the reverse ordering from the provided `ordNumber`). +// +// Sure, we could just use `sortNumbers` defined earlier and then reverse the +// whole array but that would be horribly inefficient wouldn't it? +// +// HINT: Any ordering can be reversed with a simple function `Ord.getDualOrd`. + export const sortNumbersDescending: ( numbers: ReadonlyArray, ) => ReadonlyArray = unimplemented; @@ -29,6 +63,16 @@ export const sortNumbersDescending: ( // SORT OPTIONAL VALUES // /////////////////////////////////////////////////////////////////////////////// +// This next function will sort an array of numbers wrapped in `Option` with +// the following constraint: `Option.none` < `Option.some(_)`. +// +// As such, we cannot simply use `ordNumber` because it has type `Ord` +// and we need an instance of `Ord>`. +// +// HINT: Some of `fp-ts` wrapper types such as `Option` do already have a way +// of building an `Ord` instance for their qualified inner type. You may want +// to take a look at `Option.getOrd`. + export const sortOptionalNumbers: ( optionalNumbers: ReadonlyArray>, ) => ReadonlyArray> = unimplemented; @@ -37,6 +81,19 @@ export const sortOptionalNumbers: ( // SORT COMPLEX OBJECTS // /////////////////////////////////////////////////////////////////////////////// +// Primitive types are nice and all, but sometimes you want to sort some values +// with many fields by considering only one of those fields with a more +// primitive type. +// +// In the next two functions, we start with an array of `Person`s which have a +// `name` and may have an `age`. One function will sort our array by alphabetic +// ordering of the person's names, and the other will sort it by the person's +// ages. +// +// HINT: You can build an instance of `Ord` specialized for a field for a +// record with many fields by declaring how to access that field and which +// primitive `Ord` instance to use. This can be achieved with `Ord.contramap`. + export interface Person { readonly name: string; readonly age: Option.Option; @@ -54,6 +111,8 @@ export const sortPersonsByAge: ( // COMBINE SORTING SCHEMES // /////////////////////////////////////////////////////////////////////////////// +// TBD + export const sortPersonsByAgeThenByName: ( person: ReadonlyArray, ) => ReadonlyArray = unimplemented;