Greg Weber
Greg Weber

Reputation: 3428

Typeclass instantiated by Polymorphic instances

I want to reuse some code like the following:

instance ToJavascript j => YesodTemplate j where toBuilder = toJavascript

This requires overlapping using wrapped instances , etc. So the solution I have seen is to use a wrapper.

newtype Wrapped a = Wrapped { unwrapped :: using a }
instance ToJavascript j => YesodTemplate (Wrapped j) j where
  toBuilder = toJavascript

I have the extra unwrapped j in there so data declaration with default functions that I can write the template class as

class YesodTemplate yt inner where
  toBuilder :: inner -> Builder
  file :: (inner -> yt) -> FilePath -> Q Exp
  file wrap fp = readFileQ fp >>= stringToTH wrap

The wrap function is a dummy to satisfy the type system. But this still won't compile.

juliusFile :: FilePath -> Q Exp juliusFile = file (Wrapped :: ToJavascript j => j -> Wrapped j) Ambiguous type variable `inner1' in the constraint: (ToJavascript inner1) arising from an expression type signature Probable fix: add a type signature that fixes these type variable(s) In the first argument one of `file', namely `(Wrapped :: ToJavascript j => j -> Wrapped j)' In the expression: file (Wrapped :: ToJavascript j => j -> Wrapped j) In an equation for `juliusFile': juliusFile = file (Wrapped :: ToJavascript j => j -> Wrapped j)

Upvotes: 1

Views: 308

Answers (1)

Greg Weber
Greg Weber

Reputation: 3428

Thanks for the help and encouragement from everyone!

What I ended up doing instead of using wrapped instances is to use a data declaration with default functions that can be overridden. This approach is a lot cleaner because there are no wrappers and no dummy variables- I think Stephen was right on that the original approach just isn't something that haskell/GHC was made for.

Upvotes: 0

Related Questions