Skip to content

Instantly share code, notes, and snippets.

@danidiaz
Last active December 31, 2020 02:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save danidiaz/3f396f92a6dda1cff87639ec4f1194df to your computer and use it in GitHub Desktop.
Save danidiaz/3f396f92a6dda1cff87639ec4f1194df to your computer and use it in GitHub Desktop.
generics-sop panic
{-# language DeriveGeneric #-}
{-# language FlexibleContexts #-}
{-# language TypeFamilies #-}
{-# language DataKinds #-}
{-# language ScopedTypeVariables #-}
{-# language TypeOperators #-}
{-# language TypeApplications #-}
import Data.List
import qualified GHC.Generics as GHC
import Generics.SOP
import qualified Generics.SOP.Type.Metadata as T
data Coffee = MkCoffee { coffeeBeans :: String
, coffeeOriginCountry :: String
, coffeeBrewMethod :: String
}
deriving (Show,GHC.Generic)
instance Generic Coffee
instance HasDatatypeInfo Coffee
type Parser = (->) String :.: (->) [(String,String)] :.: Maybe
parser :: Parser String
parser = Comp $ \k -> Comp $ Data.List.lookup k
parse :: forall r xs mn dn cn fs.
(IsProductType r xs,
All ((~) String) xs,
DatatypeInfoOf r ~ T.ADT mn dn '[T.Record cn fs],
T.DemoteFieldInfos fs xs)
=> [(String,String)] -> Maybe r
parse assoclist =
let fields = T.demoteFieldInfos (Proxy @fs) :: NP FieldInfo xs
parsers = hcpure (Proxy @((~) String)) parser :: NP Parser xs
Comp parsefunc = hsequence $ hliftA2 (\finfo (Comp f) -> f (fieldName finfo)) fields parsers
in to . SOP . Z <$> parsefunc assoclist
main :: IO ()
main = print $ parse @Coffee [("coffeeBeans","foo"),
("coffeeOriginCountry","bar"),
("coffeeBrewMethod","Baz")]
-- *Main> :main
-- Just (MkCoffee {coffeeBeans = "foo", coffeeOriginCountry = "bar", coffeeBrewMethod = "Baz"})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment