Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase flexibility to specify rows #13

Open
muesli4 opened this issue Sep 27, 2020 · 0 comments
Open

Increase flexibility to specify rows #13

muesli4 opened this issue Sep 27, 2020 · 0 comments

Comments

@muesli4
Copy link
Owner

muesli4 commented Sep 27, 2020

At the moment, row types are lists of the same type. This is not necessary at all and may be providing too much flexibility and too little at the same time:

  • The type does not encode the width of the data. Sometimes this is helpful as the number of columns can be dynamic but often this is not required.
  • Different columns may have different types that are an instance of Cell.

It turns out that this can be solved with little effort:

{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleInstances #-}

import Data.Foldable

class Cell a where
    buildCell :: a -> String

newtype Wrapped = Wrapped String

instance Cell String where
    buildCell = id

instance Cell Wrapped where
    buildCell (Wrapped s) = s

data AnyCell = forall c. Cell c => AnyCell c

class Row a where
    toCellList :: a -> [AnyCell]

instance {-# OVERLAPPING #-} (Cell a, Cell b) => Row (a, b) where
    toCellList (x, y) = [AnyCell x, AnyCell y]

instance (Cell a, Cell b, Cell c) => Row (a, b, c) where
    toCellList (x, y, z) = [AnyCell x, AnyCell y, AnyCell z]

instance {-# OVERLAPPABLE #-} (Foldable f, Cell a) => Row (f a) where
    toCellList xs = AnyCell <$> toList xs

str :: Row r => r -> String
str r = unwords $ map f $ toCellList r
  where
    f (AnyCell c) = buildCell c

main :: IO ()
main = do
    test ("foo", Wrapped "bar", "baz")
    test (Wrapped "foo", "bar")
    test [Wrapped "x", Wrapped "y", Wrapped "z"]
  where
    test :: forall r. Row r => r -> IO ()
    test = putStrLn . str

Alternatively, one could also provide an instance for HList and use instances from tuple-hlist to define those.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant