Please wait... The interactive code snippets on this page take a moment to render.

All the code snippets on this page are live and interactive powered by the klipse plugin.


Partial Lenses Exercises · Gitter GitHub stars npm

This page contains exercises for the Partial Lenses library. Each exercise asks you to implement an optic or transform using Partial lenses. An acceptable solution will then make all the test( ... ) cases to log Ok. In case a test( ... ) doesn't pass it logs Error and the (wrong) result.

Most of the exercises include hints that you can reveal by placing the pointer over them. The hints are written with a particular solution in mind, but it is often possible to solve a particular exercise in more than one way.

Suggestions for additional exercises are welcome!

Contents

Lenses

Getter and Setter

const lens = L.lens(
  /* getter: */ whole => '???',
  /* setter: */ (part, whole) => '???'
)

const whole = {
  part: 101
}

test('get', L.get(lens, whole), 101)
test('set', L.set(lens, 42, whole), {part: 42})
test('mod', L.modify(lens, R.negate, whole), {part: -101})

test('no-mutate', whole, {part: 101})

Nested objects

const lens = '???'

const nested = {
  inside: {
    part: 101,
    more: 'stuff'
  }
}

test('get', L.get(lens, nested), 101)
test('set', L.set(lens, 42, nested), {inside: {part: 42, more: 'stuff'}})
test('mod', L.modify(lens, R.negate, nested), {
  inside: {part: -101, more: 'stuff'}
})
test('rem', L.remove(lens, nested), undefined)

Association list

const valOf = key => '???'

const data = [{key: 'en', val: 'Title'}, {key: 'sv', val: 'Rubrik'}]

test('get', L.get(valOf('en'), data), 'Title')
test('set', L.set(valOf('en'), 'The title', data), [
  {key: 'en', val: 'The title'},
  {key: 'sv', val: 'Rubrik'}
])
test('rem', L.remove(valOf('en'), data), [{key: 'sv', val: 'Rubrik'}])

test('emp', L.remove(valOf('sv'), L.remove(valOf('en'), data)), [])

test('ins', L.set(valOf('fi'), 'Otsikko', data), [
  {key: 'en', val: 'Title'},
  {key: 'fi', val: 'Otsikko'},
  {key: 'sv', val: 'Rubrik'}
])

Dimorphic ranges

const end = '???'

test('get_num', L.get(end, {start: 1, num: 2}), 3)
test('get_end', L.get(end, {start: 1, end: 3}), 3)

test('set_num', L.set(end, 4, {start: 1, num: 2}), {start: 1, num: 3})
test('set_end', L.set(end, 4, {start: 1, end: 3}), {start: 1, end: 4})

test('set_ext', L.set(end, 4, {start: 1, num: 2, xtra: 'field'}), {
  start: 1,
  num: 3,
  xtra: 'field'
})

Traversals

Xces

const xs = '???'

const coords = [
  {x: 3, y: 9},
  {x: 1, y: 2},
  {x: 4, y: 6},
  {x: 1, y: 5},
  {x: 5, y: 3}
]

test('max', L.maximum(xs, coords), 5)

test('neg', L.modify([xs, L.when(x => 3 < x)], R.negate, coords), [
  {x: 3, y: 9},
  {x: 1, y: 2},
  {x: -4, y: 6},
  {x: 1, y: 5},
  {x: -5, y: 3}
])

test('rem', L.remove([xs, L.when(x => x < 3)], coords), [
  {x: 3, y: 9},
  {x: 4, y: 6},
  {x: 5, y: 3}
])

test('emp', L.remove([xs, L.when(x => 0 < x)], coords), [])

Nested properties

const nonObjects = '???'

test('max', L.maximum(nonObjects, {a: 1, b: {c: 2, d: {e: 5}}, e: 3}), 5)
test('mod', L.modify(nonObjects, R.of, {x: {y: {z: {w: 1}}}}), {
  x: {y: {z: {w: [1]}}}
})

Isomorphisms

Inverse puzzle

const iso = '???'

test(
  'inv',
  L.getInverse(L.inverse(iso), '{"foo":[true,false,true]}'),
  '{"bar":[false,true,false]}'
)
test('get', L.get(L.inverse(iso), '{"bar":[true]}'), '{"foo":[false]}')

Transforms

Increment and Decrement

const trn = '???'

test(
  'sol',
  L.transform(trn, {xs: {a: 3, b: 1, c: 4}, ys: [1, 5, 9]}),
  /**/ {xs: {a: 4, b: 2, c: 5}, ys: [0, 4, 8]}
)

        document.querySelector('.loading-message').className = "loading-hidden";
        ga('send', 'event', 'completed', 'load', Math.round((Date.now() - startTime)/1000));
        accelerate_klipse();