4 ms·
I get it! (Thanks, playing around with actual code helped a ton.) For example, in Typescript you're saying you can add a default value simply: # old fu
by itishappy 2y ago
I get it! (Thanks, playing around with actual code helped a ton.) For example, in Typescript you're saying you can add a default value simply:
# old
function f(x: number): number {
return 2 * x;
}
# new
function f(x: number|null): number {
x = x || 3;
return 2 * x;
}
# usage
# old
f(2)
# new
f(2) # still works!
But in Haskell this requires changing the call sites:
-- old
f :: Int -> Int
f = (*2)
-- new
f :: Maybe Int -> Int
f = maybe 0 (*2)
-- usage
-- old
f 2
-- new
f (Just 2) -- different!
But I actually feel this is an antipattern in Haskell (and maybe TypeScript too), and a separate wrapper function avoids refactoring while making things even more user friendly.
-- old
f :: Int -> Int
f = (*2)
-- new
fMaybe :: Maybe Int -> Int
fMaybe = maybe 3 f
-- usage
-- old
f 2
-- new
f 2 -- still works!
fMaybe Nothing -- works too!
Here's some wrappers for general functions (not that they're needed, they're essentially just raw prelude functions):
maybeIn :: b -> (a -> b) -> (Maybe a -> b)
maybeIn = maybe
maybeOut :: (a -> b) -> (a -> Maybe b)
maybeOut = fmap Just
maybeBoth :: b -> (a -> b) -> (Maybe a -> Maybe b)
maybeBoth d = maybeOut . maybeIn d
Added bonus, this approach avoids slowing down existing code with the null checks we just added.
- itishappy 2y agoGot `maybeOut` wrong, can't edit, but it should be: maybeOut :: (a -> b) -> (a -> Maybe b) maybeOut = (.) Just Also the parenthesis around the last two output types are added for emphasis, but can be safely removed.
- itishappy 2y agoLast reply. Probably. Here's `maybe` in TypeScript: const maybe = <T,>(f: (_: T) => T, d:T) => (x: T|null) => f(x || d); console.log(maybe((x) => 2 * x, 3)(null)); // returns: 6