Skip to content
New issue

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

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

Already on GitHub? # to your account

makeShowHF doesn't work for lists #34

Open
liarokapisv opened this issue Mar 10, 2021 · 2 comments
Open

makeShowHF doesn't work for lists #34

liarokapisv opened this issue Mar 10, 2021 · 2 comments

Comments

@liarokapisv
Copy link

liarokapisv commented Mar 10, 2021

First of all thanks for the incredible library! I am using it on a compiler project and the Data.Comp.Multi modules have been incredibly useful for manipulting the AST.

One problem that I have encountered is that makeShowHF does not work for lists or maybe values. All other derivations work perfectly!

Here is a minimal example:

data Expr
data Stmt

data T r i where
    ExprInt :: Int -> T r Expr
    ExprAdd :: r Expr -> r Expr -> T r Expr
    ProcCall :: String -> [r Expr] -> T r Stmt

This fails with:

    • Couldn't match expected type ‘Data.Comp.Multi.HFunctor.K
                                      String i0’
                  with actual type ‘[Data.Comp.Multi.HFunctor.K String Expr]’
    • In the first argument of ‘Data.Comp.Multi.HFunctor.unK’, namely
        ‘x_a4jN’
      In the expression: Data.Comp.Multi.HFunctor.unK x_a4jN
      In the second argument of ‘compdata-0.12.1:Data.Comp.Multi.Derive.Show.showConstr’, namely
        ‘[show x_a4jM, Data.Comp.Multi.HFunctor.unK x_a4jN]’


I can get around this via hacks but it's not really ergonomic:

data Expr
data Stmt

data T r i where
    (:-:) :: r a -> r [a] -> T r [a]
    Nil :: T r [a]
    ExprInt :: Int -> T r Expr
    ExprAdd :: r Expr -> r Expr -> T r Expr
    --not really equivalent!
    ProcCall :: String -> r [Expr] -> T r Stmt

The equivalent seems to work for makeShowF so I thought maybe this was worth reporting.

@liarokapisv liarokapisv changed the title makeShowHF doesn't work for list, maybe arguments. makeShowHF doesn't work for lists Mar 10, 2021
@liarokapisv
Copy link
Author

After digging through the code it seems the following lines in the makeShowHF function create the problem:

mkShow (isFArg, var)
                | isFArg = [|unK $var|]
                | otherwise = [| show $var |]

In our case [r Expr] does indeed contain r so the isFArg is chosen.
I can fix my problem by modifying the above like so:

mkShow (ty, isFArg, var)
                | isFArg = case ty of
                                AppT ListT _ -> [|show (fmap (NoQuotes . unK) $var) |]
                                _  -> [|unK $var|]
                | otherwise = [| show $var |]

NoQuotes is a simple wrapper over string that does not print quotes. This has the advantage that the ListT implementation holds for any Showable functor and not just lists. I think this would be a great enhancement to the library. Off the top of my mind one should be able to distinguise the r _ and t (r _) cases in the mkShow sub-function and be able to query if t is a Functor. It should be a minimal change overall. I can probably do it myself if you agree with this and are willing to accept a PR.

@liarokapisv
Copy link
Author

Another option is something like this:

newtype NoQuotes = NoQuotes String
instance Show NoQuotes where show (NoQuotes str) = str

newtype W f = W { unW :: f }

instance Show (W (K String i)) where
    show = unK . unW

instance (Functor f, Show (f NoQuotes)) => Show (W (f (K String i))) where
    show = show . fmap (NoQuotes . unK) . unW

mkShow (isFArg, var)
        | isFArg = [| show (W $var) |]
        | otherwise = [| show $var |]

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant