Last active
October 30, 2018 05:17
-
-
Save matfournier/805489b25e111ab4090d18a45817bcce to your computer and use it in GitHub Desktop.
Playing with haskell to solve a scala problem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- so I have a problem where I had some ADT. I need to produce some FinalResult at a | |
-- much later time where the ADT is some input on the way to getting this final result | |
-- Each member of the ADT needs some different piece of missing information required to produce the final result | |
-- at some point we end up with this missing information | |
-- to get the final result, pattern match on the ADT and provide the correct bit of missing info | |
-- leads to a lot of pattern matching in Scala. | |
-- Typeclass looks nicer but feels just like moving the pattern match around | |
-- and looks 100x uglier in scala due to cruft/implicits | |
-- alternatives? | |
-- in my scala code I don't necessarily have the MissingInformation all bundled up into some type | |
-- I have a class that has a bunch of info (some of which is most of the MissingInformation) and one of the ADTs | |
-- and some fn call that provides the remaining bit of MissingInformation needed to combine it all together to | |
-- get the final result. | |
-- trying to lean less on pattern matching but don't see a solution? | |
data FinalResult = FinalResult Int deriving Show | |
data Inputs = Input1 Int | |
| Input2 Int Int | |
| Input3 String | |
deriving Show | |
-- say Input 1 needs some later String to be provided to get to FinalResult | |
-- Input 2 needs some later () to be provided to get to FinalResult | |
-- Input 3 needs some Int to be provided to get to FinalResult | |
data MissingInformation = MissingInformation { s :: String | |
, i :: Int} | |
-- straight up pattern matching | |
inputToFinal :: Inputs -> MissingInformation -> FinalResult | |
inputToFinal (Input1 i) (MissingInformation s _) = FinalResult $ i + read s | |
inputToFinal (Input2 i j) (MissingInformation _ _) = FinalResult $ i + j | |
inputToFinal (Input3 s) (MissingInformation _ i) = FinalResult $ read s + i | |
-- via typeclasses, but isn't this just shifting the pattern match? | |
-- this is all fine but is super heavy on the pattern matching (it looks MUCH worse in scala) | |
-- the type class soln helps, but feels like it just moves the pattern match somewhere else | |
-- and is 10x as ugly in Scala w/ implicits | |
class GivesFinalResult a where | |
invoke :: a -> MissingInformation -> FinalResult | |
instance GivesFinalResult Inputs where | |
invoke (Input1 i) (MissingInformation s _) = FinalResult $ i + read s | |
invoke (Input2 i j)(MissingInformation _ _) = FinalResult $ i + j | |
invoke (Input3 s)(MissingInformation _ i) = FinalResult $ read s + i | |
-- constrain the type here | |
input2Final :: (GivesFinalResult i) => i -> MissingInformation -> FinalResult | |
input2Final inputs missing = invoke inputs missing | |
-- q: how to avoid explosion of types if new Inputs are added | |
-- esp if they also need new MissingInformation | |
-- followup q: what if Inputs was 30 types? How would you do this differently | |
-- q: what if Inputs was several things? | |
-- a: I think... who cares as long as they implement GivesFinalResult | |
-- q: alternatives to this? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment