Unwrap Pair with two Maybes
janczer opened this issue ยท 4 comments
Can you help me please. I'm trying to refactor my code and I'm stuck with unwrap Pair.
Here is my code:
const code = 'aabbc'; // valid litera code
// const code = '1231231233'; // valid numerical code
// const code = '123123aaaaa'; // invalid code
const isNumberCode = code => !!/^[0-9]{10}$/.exec(code);
const isLiteralCode = code => !!/^[A-Za-z]{5}$/.exec(code);
// flow :: a -> Pair a a
const flow = code => Pair(code, code)
const numberJust = code => Just({id: code})
const literalJust = code => Just({serial: code})
const isNumberCodeMaybe = ifElse(isNumberCode, numberJust, Nothing)
const isLiteralCodeMaybe = ifElse(isLiteralCode, literalJust, Nothing)
const result =
flow(code)
.bimap(isNumberCodeMaybe, isLiteralCodeMaybe)
// here I want unwrap the result
I want write the function that merge or unwrap the Pair:
// Pair Just Nothing -> Just
// Pair Nothing Just -> Just
// Pair Nothing Nothing -> Nothing
Can you help me please?
Hey, what you're looking for is merge
and alt
. merge
will take a function that expects two arguments which will be both sides of the Pair
. If we pass in the Maybe
's pointfree function alt
we'll get the behaviour you're chasing
import { Maybe, Pair, merge, alt, map } from 'crocks'
const { Just, Nothing } = Maybe
const unwrap = merge(alt)
unwrap(Pair(Just('something'), Nothing()))
//=> Just "something"
unwrap(Pair(Nothing(), Just('something')))
//=> Just "something"
unwrap(Pair(Nothing(), Nothing()))
//=> Just "something"
There are a few improvements we can make to your code, i'll throw up an example in a bit
So this is probably not the best put it removes the need for Pair
and the potential confusion when looking at the code
import { Maybe, Pair, merge, alt, map, ifElse, fanout, when, objOf, constant, or, unless } from 'crocks'
const { Just, Nothing } = Maybe
// const code = 'aabbc'; // valid litera code
// const code = '1231231233'; // valid numerical code
const code = '123123aaaaa'; // invalid code
const testOn = regex => code => RegExp(regex).test(code)
const isNumberCode = testOn(/^[0-9]{10}$/);
const isLiteralCode = testOn(/^[A-Za-z]{5}$/);
Just(code)
.map(unless(or(isNumberCode, isLiteralCode), Nothing))
.map(when(isNumberCode, objOf('id')))
.map(when(isLiteralCode, objOf('serial')))
Thank you! Your improved code looks very good!
I'm glad you like it, let us know if you have any other questions