Created
October 30, 2017 15:25
-
-
Save kutyel/d9fa429155021c933015bbc6c5df32b2 to your computer and use it in GitHub Desktop.
Professor Frisby's functional programming exercises (Part 3: functors)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require('./support') | |
const expect = require('expect') | |
const Task = require('data.task') | |
const { | |
add, | |
curry, | |
compose, | |
concat, | |
prop, | |
map, | |
head, | |
toUpper, | |
} = require('ramda') | |
// Exercise 1 | |
// ========== | |
// Use _.add(x,y) and _.map(f,x) to make a function that increments a value | |
// inside a functor. | |
// ex1 :: Number -> Number | |
const ex1 = map(add(1)) | |
expect(ex1(Identity.of(1))).toEqual(Identity.of(2)) | |
// Exercise 2 | |
// ========== | |
// Use _.head to get the first element of the list. | |
const xs = Identity.of(['do', 'ray', 'me', 'fa', 'so', 'la', 'ti', 'do']) | |
const ex2 = map(head) | |
expect(ex2(xs)).toEqual(Identity.of('do')) | |
// Exercise 3 | |
// ========== | |
// Use safeProp and _.head to find the first initial of the user. | |
const safeProp = curry((x, o) => Maybe.of(o[x])) | |
const user = { | |
id: 2, | |
name: 'Albert', | |
} | |
// ex3 :: User -> String | |
const ex3 = compose(map(head), safeProp('name')) | |
expect(ex3(user)).toEqual(Maybe.of('A')) | |
// Exercise 4 | |
// ========== | |
// Use Maybe to rewrite ex4 without an if statement. | |
// const ex4 = function(n) { | |
// if (n) { | |
// return parseInt(n) | |
// } | |
// } | |
// ex4 :: Number -> Maybe(Number) | |
const ex4 = compose(map(parseInt), Maybe.of) | |
expect(ex4('4')).toEqual(Maybe.of(4)) | |
// Exercise 5 | |
// ========== | |
// Write a function that will getPost then toUpperCase the post's title. | |
// getPost :: Int -> Future({id: Int, title: String}) | |
const getPost = i => | |
new Task((_, res) => | |
setTimeout( | |
() => | |
res({ | |
id: i, | |
title: 'Love them futures', | |
}), | |
300 | |
) | |
) | |
const _upperTitle = compose(toUpper, prop('title')) | |
const ex5 = compose(map(_upperTitle), getPost) | |
ex5(1).fork(console.log, title => expect(title).toBe('LOVE THEM FUTURES')) | |
// Exercise 6 | |
// ========== | |
// Write a function that uses checkActive() and showWelcome() to grant access | |
// or return the error. | |
const showWelcome = compose(concat('Welcome '), prop('name')) | |
const checkActive = user => | |
user.active ? Right.of(user) : Left.of('Your account is not active') | |
// ex6 :: User -> Either String String | |
const ex6 = compose(map(showWelcome), checkActive) | |
expect(ex6({ name: 'Flavio', active: true })).toEqual( | |
Right.of('Welcome Flavio') | |
) | |
expect(ex6({ name: 'Yannick', active: false })).toEqual( | |
Left.of('Your account is not active') | |
) | |
// Exercise 7 | |
// ========== | |
// Write a validation function that checks for a length > 3. It should return | |
// Right(x) if it is greater than 3 and Left("You need > 3") otherwise. | |
// ex7 :: String -> Either String String | |
const ex7 = x => (x.length > 3 ? Right.of(x) : Left.of('You need > 3')) | |
expect(ex7('hello')).toEqual(Right.of('hello')) | |
expect(ex7('fla')).toEqual(Left.of('You need > 3')) | |
// Exercise 8 | |
// ========== | |
// Use ex7 above and Either as a functor to save the user if they are valid or | |
// return the error message string. Remember either's two arguments must return | |
// the same type. | |
const save = x => new IO(() => (console.log('SAVED USER!'), x + '-saved')) | |
const ex8 = compose(either(IO.of, save), ex7) | |
expect(ex8('flavio').unsafePerformIO()).toBe('flavio-saved') | |
expect(ex8('fla').unsafePerformIO()).toBe('You need > 3') | |
console.info('You are now a FUNCTOR genius!!! π€ ππΌ ππΌ ππΌ') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment