-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Natural Transformation #2
Comments
Actually, const log = msg => x => (console.log (msg, x), x)
const logError = msg => x => (console.error (msg, x), x)
const parseJson = S.encase (JSON.parse)
// futureParseJson :: Error a, Object b => String -> Future a b
const futureParseJson = S.pipe ([
parseJson,
log ('after parseJson'), // <- debugging
eitherToFuture,
])
const getJson = S.pipe ([
futureParseJson,
fork
(logError ('Rejection:'))
(log ('Resolved:')),
])
// main
const validJsonString = '[{"foo":"bar"},{"foo":null}]'
const invalidJsonString = '[{"foo":"bar"}{"foo":null}]'
getJson (validJsonString)
// -> after parseJson Right ([{"foo": "bar"}, {"foo": null}])
// Resolved: [ { foo: 'bar' }, { foo: null } ]
getJson (invalidJsonString)
// -> after parseJson Left (new SyntaxError ("Unexpected token { in JSON at position 14"))
// Rejection: SyntaxError: Unexpected token { in JSON at position 14
// at parse (<anonymous>) |
Perhaps unsubscribe should be mention as well but now it gets complicated... // parseJson :: Error a, Object b => String -> Future a b
const parseJson = S.compose (eitherToFuture) (S.encase (JSON.parse))
// getJson :: String -> Function
const getJson = S.pipe ([
parseJson,
fork
(logError ('Rejection:'))
(log ('Resolved:')),
])
// main
const validJsonString = '[{"foo":"bar"},{"foo":null}]'
const invalidJsonString = '[{"foo":"bar"}{"foo":null}]'
getJson (validJsonString) // <- unsubscribe
// Resolved: [ { foo: 'bar' }, { foo: null } ]
getJson (invalidJsonString) // <- unsubscribe
// Rejection: SyntaxError: Unexpected token { in JSON at position 14
// at parse (<anonymous>) On second thought, I think unsubscribe should have its own section... |
@Avaq just pointed out that const eitherToFuture = S.either (Future.reject) (Future.resolve)
|
@dotnetCarpenter thanks a lot. I'll work through your comments. Feel free to prepare a PR. |
Thank for the attention @jceb. I still feel that I haven't articulated a nice overview of natural transformation with Fluture yet. Probably we need to brainstorm this together before it will get any good. Having I'm not sure if swap :: Pair a b -> Pair b a and // swap :: Either a b -> Either b a
const swap = S.either (S.Right) (S.Left); The latter can be used instead of
parseImageType :: ImageType -> Buffer -> Either Buffer Image // parseGif :: Buffer -> Either Buffer Image
const parseGif = parseImageType ('gif');
// parsePng :: Buffer -> Either Buffer Image
const parsePng = parseImageType ('png');
// parseJpg :: Buffer-> Either Buffer Image
const parseJpg = parseImageType ('jpeg');
// parseImage :: Buffer-> Either Buffer Image
const parseImage = S.pipe ([
S.Right, // <- Right Buffer
S.chain (S.compose (swap) (parseGif)), // <- Right Buffer | Left Image
S.chain (S.compose (swap) (parsePng)), // <- Right Buffer | Left Image
S.chain (S.compose (swap) (parseJpg)), // <- Right Buffer | Left Image
swap, // <- Left Buffer | Right Image
]);
doSomethingUsefulWithAnImage :: Image -> a
IMPURE_displayParseError :: Buffer -> a S.either (IMPURE_displayParseError) // sad path
(doSomethingUsefulWithAnImage) // happy path
(parseImage (buffer)) Case analysis is also something that I feel needs explaining. It's the pattern matching feature of Sanctuary and usually final stop for data transformations. // Example of sanctuary style pattern match using lower case ADT names
// This example show case how to deal with nested ADT's. Note that
// this kind of pattern matching is destructive, e.i. we will loose the type.
const { maybe, either, pair, show, Nothing, Just, Left, Right, Pair } = S
const patternMatch =
maybe ('It was Nothing')
(either (pair (i => s => `It was Left of Pair with ${show (i)} and ${s}`))
(s => `It was Right with: ${s}`))
console.log (patternMatch (Nothing))
console.log (patternMatch (Just (Left (Pair (42) ('What is the meaning of life, the universe, and everything?')))))
console.log (patternMatch (Just (Right ('Sanctuary')))) Above was an example provided by @Avaq |
I like the example of parsing JSON, because many people want to do that. However, it lacks the try this, try that style of the parsing images example. Maybe we could combine the two: parse a JSON file, check if an error is included - think JSON API, otherwise return the data. I'd say let's not define functions with |
In the Fluture section, it could be useful to mention Natural Transformation as described in https://github.com/MostlyAdequate/mostly-adequate-guide/blob/master/ch11.md.
I find the following natural transformation of an Either to Future very useful:
One use-case could be parsing JSON:
What do you think?
The text was updated successfully, but these errors were encountered: