Skip to content

Instantly share code, notes, and snippets.

@josephcsible
Last active June 2, 2020 21:05
Show Gist options
  • Save josephcsible/b2ac3e76881d9f4a17f1bac5fbab733f to your computer and use it in GitHub Desktop.
Save josephcsible/b2ac3e76881d9f4a17f1bac5fbab733f to your computer and use it in GitHub Desktop.
"Obvious" refactors can be wrong
{-# OPTIONS -Werror=type-defaults #-}
import Data.Maybe (isJust)
import Data.Word (Word16, byteSwap16)
default ()
oneNumTup :: Num a => (a, a)
oneNumTup = (2, 300)
doSomethingWith :: Integral a => Word16 -> a -> Maybe (Word16, a)
doSomethingWith x y = if byteSwap16 x > 10 && (y * 400) `div` 400 == y then Just (x,y) else Nothing
foo :: Num a => (a, Integer) -> a
foo (x,y) = x + fromInteger y
main :: IO ()
main = print $ isJust (fmap foo bar)
where bar = doSomethingWith (fst oneNumTup) (snd oneNumTup)
{-
Even with no type defaulting, no bottoms, and no unlawful instances, seemingly-obvious refactors
like `f (fst x) (snd x) = uncurry f x` and `isJust (fmap f x) = isJust x` can be wrong. This
program is a concrete example: applying both of those will make it print False instead of True.
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment