Solving IsSymbol instances#2429
Solving IsSymbol instances#2429paf31 merged 4 commits intopurescript:masterfrom LiamGoodacre:feature/is-symbol-instances
Conversation
| = TypeClassDictionaryInScope { | ||
| -- | The identifier with which the dictionary can be accessed at runtime | ||
| tcdName :: Qualified Ident | ||
| tcdName :: n |
There was a problem hiding this comment.
Could we just make this into an Expr?
There was a problem hiding this comment.
I think I tried something like that previously (think it was Either Expr (Qualified Ident)) but it caused a module dependency cycle. I'll have another look later today.
| -- ^ Should the solver be allowed to defer errors by skipping constraints? | ||
| } | ||
|
|
||
| -- TODO: Where would this live? |
There was a problem hiding this comment.
I think it's fine here. I was planning to move the deriving logic here later too, to get around the type synonym restrictions.
|
Looks great, thanks! Yes, you'll have some issues with library versions if you update them all to v2.0 like that. There is an issue to track the update that needs to happen (#2400) but it's probably quite a bit of work. Maybe you can avoid it for now? |
|
In that case I should probably use |
| import Control.Monad.Eff.Console | ||
|
|
||
| main = do | ||
| log (reflectSymbol (SProxy :: SProxy "literal")) |
There was a problem hiding this comment.
How about checking the result too ?
let
a = (reflectSymbol (SProxy :: SProxy "literal"))
b = (reflectSymbol (SProxy :: SProxy (TypeConcat "Hello" "World")))
when (a == "literal" && b == "HelloWorld") (log "Done")
There was a problem hiding this comment.
Sounds good, thanks
There was a problem hiding this comment.
(also I didn't realise outputting Done was interpretted as 'test passing')
| [ ("reflectSymbol", Abs (Left (Ident C.__unused)) (Literal (StringLiteral sym))) | ||
| ] | ||
| classTy = TypeConstructor (fmap coerceProperName C.IsSymbol) | ||
| expr = TypedValue False (Literal inst) (TypeApp classTy (TypeLevelString sym)) |
There was a problem hiding this comment.
I wasn't sure about TypedValue - have I done this correctly? I didn't work out what the boolean argument was for and I didn't see it mentioned in the doc-comment for the constructor.
There was a problem hiding this comment.
Do we need TypedValue here? I think it can be removed actually.
There was a problem hiding this comment.
It appeared to be required by exprToCoreFn in src/Language/PureScript/CoreFn/Desugar.hs here:
exprToCoreFn ss com _ (A.TypeClassDictionaryConstructorApp name (A.TypedValue _ (A.Literal (A.ObjectLiteral vs)) _)) =Otherwise it hits the error case:
exprToCoreFn _ _ _ e =
error $ "Unexpected value in exprToCoreFn mn: " ++ show eThere was a problem hiding this comment.
Maybe you could add a case for
exprToCoreFn ss com _ (A.TypeClassDictionaryConstructorApp name (A.Literal (A.ObjectLiteral vs))) =
or use a pattern guard here then?
|
@paf31: making The following is a trimmed down version of our modules and their dependencies: We need |
|
An alternative might be to remove the name/expr from TypeClassDictionaryInScope and just pair the dict up with the Expr where needed. I'll have a think about it. |
|
Although that is actually the same solution as what I've already done with adding the type parameter. |
|
@LiamGoodacre I think we should stick with the original approach actually, using a sum type, now that I understand the problem properly (sorry!) But let's rename some things to make them more understandable:
|
| , tcdDependencies :: Maybe [Constraint] | ||
| } | ||
| deriving (Show) | ||
| deriving (Show, Functor) |
There was a problem hiding this comment.
Might as well derive the usual Functor, Foldable and Traversable here.
|
A third option is a sum type like data Evidence
= NamedDictionary Ident
| IsSymbolDictionary Stringright? |
|
I can confirm that this makes my I did run into one weird issue though. If I don't import |
|
I think there is relatively little needed to push this over the finish line, right? Just
I think once this is merged, we should release 0.10.3, since it will enable some nice library features which depend on |
|
Hey thanks for the review. I've been away without internet for a few days so I haven't had a chance to work on this. I should be able to get this done today/tomorrow though 👍 |
|
I've been looking into the |
|
@garyb yeah that makes sense, thanks. So we'll need to implicitly import the type class constructor during code gen - what would be the preferred way of doing that? |
|
Hmm, that's a tricky one actually... I'm not too sure! Probably as part of the |
| fqValues :: A.Expr -> [ModuleName] | ||
| fqValues (A.Var q) = getQual' q | ||
| fqValues (A.Constructor q) = getQual' q | ||
| fqValues (A.TypeClassDictionaryConstructorApp C.IsSymbol _) = getQual' C.IsSymbol |
There was a problem hiding this comment.
This lets us implicitly add an import of Data.Symbol if the IsSymbol class is used. The import also gets deduped later if it's already there.
Is this a good place to add this?
There was a problem hiding this comment.
Perhaps it's not great to explicitly mention IsSymbol here: it means we'd have to update multiple places if we're to do similar instance solving in the future. But it's possibly odd to do it for all constructor applications?
There was a problem hiding this comment.
Could you please add a comment here explaining why this line is necessary?
| import qualified Language.PureScript.Constants as C | ||
|
|
||
| type TypeClassDict = | ||
| TypeClassDictionaryInScope (Either Expr (Qualified Ident)) |
There was a problem hiding this comment.
I think I'd rather use a sum type here, with a constructor for named instances, and one for symbol dictionaries. Then instead of using either id in mkDictionary, you would pattern match, and include the instance generation code there. isSymbolDictionary would just apply the appropriate constructor.
| } | ||
|
|
||
| -- | Build a type class instance dictionary for the `IsSymbol` class for a symbol | ||
| isSymbolDictionary :: String -> TypeClassDict |
There was a problem hiding this comment.
I originally read this as a question: "is this a symbol dictionary?" 😄
Maybe something like makeIsSymbolDictionary would be better?
|
Currently updating the test example so that it depends on the implicit importing. |
|
Okay I'm confused: the test is passing on some build jobs and failing on others 😕. |
|
I think you need to update the cabal file. |
|
Nice work! |
Opening this PR for discussion: there are some TODOs and other things.
Currently many of the
exampletests fail since I updatedtests/support/bower.jsonto specify the current latest versions of libraries. They fail withThe foreign module implementation for module Unsafe.Coerce is missing.. I addedpurescript-unsafe-coerceas a dependency, but it didn't help. So I'm not sure why that fails.However my
SolvingIsSymboltest does pass 👍