Skip to content

Instantly share code, notes, and snippets.

@kosmikus
Created March 27, 2018 21:46
Show Gist options
  • Save kosmikus/9b72416652cda4fd054ffc4c67d0d167 to your computer and use it in GitHub Desktop.
Save kosmikus/9b72416652cda4fd054ffc4c67d0d167 to your computer and use it in GitHub Desktop.
sop-based generic editor
{-# LANGUAGE FlexibleContexts, MultiParamTypeClasses, GADTs, DefaultSignatures, DeriveAnyClass, StandaloneDeriving, ScopedTypeVariables, TypeApplications #-}
module Buildable where
import Generics.SOP
import Generics.SOP.Metadata
class Buildable a where
build :: IO a
default build :: (Generic a, HasDatatypeInfo a, All2 Buildable (Code a)) => IO a
build = gbuild
instance Buildable Int where
build = do
putStrLn $ "Provide integer:"
readLn
gbuild :: forall a . (Generic a, HasDatatypeInfo a, All2 Buildable (Code a)) => IO a
gbuild = do
putStrLn $ "Select a constructor: " ++ show (zip [0..] (conNames (Proxy @a)))
n <- readLn
to <$> choose' n
choose' :: (All SListI xss, All2 Buildable xss) => Int -> IO (SOP I xss)
choose' n = map hsequence (apInjs_POP (hcpure (Proxy @Buildable) build)) !! n
conNames :: (SListI (Code a), HasDatatypeInfo a) => Proxy a -> [String]
conNames p = hcollapse (hmap (K . constructorName) (constructorInfo (datatypeInfo p)))
deriving instance Buildable Bool
deriving instance Buildable a => Buildable [a]
{-
> gbuild :: IO (Either Int [Bool])
Select a constructor: [(0,"Left"),(1,"Right")]
0
Provide integer:
5
Left 5
> gbuild :: IO (Either Int [Bool])
Select a constructor: [(0,"Left"),(1,"Right")]
1
Select a constructor: [(0,"[]"),(1,":")]
1
Select a constructor: [(0,"False"),(1,"True")]
1
Select a constructor: [(0,"[]"),(1,":")]
1
Select a constructor: [(0,"False"),(1,"True")]
0
Select a constructor: [(0,"[]"),(1,":")]
0
Right [True,False]
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment