mostly-adequate-guide icon indicating copy to clipboard operation
mostly-adequate-guide copied to clipboard

Chapter 8 references 'find' function that is not present in the appendix

Open ktr opened this issue 4 years ago • 5 comments

Chapter 8 has a section that references a find function:

// findParam :: String -> IO Maybe [String]
const findParam = key => map(compose(Maybe.of, find(compose(eq(key), head)), params), url);

But there does not appear to be a find function in the Appendix. I believe this may have referenced filter before (per issue #303) and there is a definition of find in there, so perhaps it just needs to be added to appendix?

Thanks for great book - enjoying very much so far!

ktr avatar Apr 21 '20 01:04 ktr

perhaps it just needs to be added to appendix?

I think you're right :)

KtorZ avatar Apr 21 '20 08:04 KtorZ

Assuming ECMAScript 2015 (ES6) the example works with the following implementation of find:

// find :: Pred a => a -> [b] -> b
const find = curry((fn, list) => list.find(fn))

dotnetCarpenter avatar Jan 12 '21 18:01 dotnetCarpenter

Here is a find implementation that follows the code style of the other Pointfree Utilities given in appendix C:

// find :: (a -> Boolean) -> [a] -> a
const find = curry(function find(fn, xs) {
  assert(
    typeof fn === 'function' && Array.isArray(xs),
    typeMismatch('(a -> Boolean) -> [a] -> a', [getType(fn), getType(xs), getType(xs)].join(' -> '), 'find'),
  );

  return xs.find(fn);
});

dotnetCarpenter avatar Jan 12 '21 18:01 dotnetCarpenter

Note, that the example does not currently work with the support.js file for the book.

Current example:

// url :: IO String
const url = new IO(() => window.location.href);

// toPairs :: String -> [[String]]
const toPairs = compose(map(split('=')), split('&'));

// params :: String -> [[String]]
const params = compose(toPairs, last, split('?'));

// findParam :: String -> IO Maybe [String]
const findParam = key => map(compose(Maybe.of, find(compose(eq(key), head)), params), url);

// -- Impure calling code ----------------------------------------------

// run it by calling $value()!
findParam('searchTerm').$value();
// Just(['searchTerm', 'wafflehouse'])

Changes needed for the example to work (assuming find implementation in support.js as mention in previous comment):

'use strict'

const {
  IO,
  compose,
  map,
  split,
  last,
  Maybe,
  find,
  eq,
  head,
} = require('../support')

const window = {}
window.location = {}
window.location.href = 'https://www.example.com/foo?bar=yes&searchTerm=wafflehouse&wedonot=care'

// url :: IO String
const url = new IO(() => window.location.href);

// toPairs :: String -> [[String]]
const toPairs = compose(map(split('=')), split('&'));

// params :: String -> [[String]]
const params = compose(toPairs, last, split('?'));

// findParam :: String -> IO Maybe [String]
const findParam = key => map(compose(Maybe.of, find(compose(eq(key), head)), params), url);

// -- Impure calling code ----------------------------------------------

// run it by calling .unsafePerformIO()!
// findParam('searchTerm').unsafePerformIO();
const result = findParam('searchTerm').unsafePerformIO();
console.log(result) // Just(['searchTerm', 'wafflehouse'])

dotnetCarpenter avatar Jan 12 '21 19:01 dotnetCarpenter

Oh no. There is 2 support.js files. One that is actually used, in this repo and @mostly-adequate/support. None of them has find but one has replace and the one (in this repo) which is actually used in the exercises, does not.

What is the correct place to add missing functions? Is there any reason to have @mostly-adequate/support as a package?

This is confusing and also the reason for https://github.com/MostlyAdequate/mostly-adequate-guide/issues/506

dotnetCarpenter avatar Jan 12 '21 22:01 dotnetCarpenter