Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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.


Got `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.


Last 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




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: