Haskell Plugins - haskell

Im using the plugins library, trying to evaluate the string
eval "id :: Test -> Test" ["Data.Test"]
where Test is
module Data.Test where
import Prelude
import Data.Typeable
data Test = TestRec { testString :: String }
deriving (Show)
deriving instance Typeable Test
I have added Data.Test to exposed modules in my .cabal file and installed the module.
However, when i run the above code I get an error
api: /tmp/MXXXXX22793.o: unknown symbol `apizm0zi0zi0_DataziTest_zdfTypeableTest_closure'
Any idea why this happens?
GHC version: 7.6.3
plugins version: 1.5.4.0
Edit: I have created a small compiling example of the bug: https://github.com/fabianbergmark/plugins-bug.git

Apparently Plugins is considered broken. Changing to hint (Example in git repository) works flawless

Related

How to profile TemplateHaskell built with Cabal?

Full project at https://github.com/ysangkok/cabal-profiling-issue
The project contains scaffolding generated by cabal init. I'll paste the most interesting source snippets now.
In Main.hs I have:
newtype Wrapper = Wrapper Int
deriveConvertible ''Wrapper ''Int
in TH.hs I have:
import Data.Convertible
deriveConvertible :: TH.Name -> TH.Name -> TH.Q [TH.Dec]
deriveConvertible newType otherType = do
Just newCon <- TH.lookupValueName (TH.nameBase newType)
v <- TH.newName "v"
[d|
instance Convertible $(TH.conT newType) $(TH.conT otherType) where
safeConvert $(TH.conP newCon [TH.varP v]) = Right $(TH.varE v)
instance Convertible $(TH.conT otherType) $(TH.conT newType) where
safeConvert source = Right ($(TH.conE newCon) source)
|]
But if I put profiling: true in cabal.project and run cabal build with GHC 8.6.5 and Cabal 3.4.0.0 (installed using ghcup), I get:
Failed to load interface for 'Data.Convertible.Base'
Perhaps you haven't installed the profiling libraries for package 'convertible-1.1.1.0'?
What is wrong with the code, and why does it compile without profiling, but fails when enabled?
It is a known problem about compile multi-module program that contains TH code for profiling, see related sections in the documentation:
This causes difficulties if you have a multi-module program containing
Template Haskell code and you need to compile it for profiling,
because GHC cannot load the profiled object code and use it when
executing the splices.
As a workaround, just put TemplateHaskell into the other-modules in your test.cabal,
other-extensions: TemplateHaskell
Then building with profiling (i.e., with the cabal build --enable-library-profiling) every thing would be ok.
For more details about why we need TemplateHaskell in other-modules section, see https://github.com/haskell/cabal/issues/5961.

Plugin name lookup behavior change from GHC 8.4 series

[Update: Turns out this was a GHC bug and it is now fixed, slated for the 8.6.4 release: https://ghc.haskell.org/trac/ghc/ticket/16104#comment:8 ]
I'm trying to port a core plugin to GHC 8.6.3, which was last working fine with GHC 8.4 series. Unfortunately, I'm running into issues. Wondering if pluging programming requirements have changed, or is this a regression in GHC itself. I boiled it down to the following example and would like some guidance on how to make this work:
I have the following in file TestPlugin.hs:
{-# LANGUAGE TemplateHaskell #-}
module TestPlugin (plugin) where
import GhcPlugins
import Data.Bits
plugin :: Plugin
plugin = defaultPlugin {installCoreToDos = install}
where install _ todos = return (test : todos)
test = CoreDoPluginPass "Test" check
check :: ModGuts -> CoreM ModGuts
check m = do mbN <- thNameToGhcName 'complement
case mbN of
Just _ -> liftIO $ putStrLn "Found complement!"
Nothing -> error "Failed to locate complement"
return m
And I have a very simple Test.hs file:
{-# OPTIONS_GHC -fplugin TestPlugin #-}
main :: IO ()
main = return ()
With GHC-8.4.2, I have:
$ ghc-8.4.2 --make -package ghc -c TestPlugin.hs
[1 of 1] Compiling TestPlugin ( TestPlugin.hs, TestPlugin.o )
$ ghc-8.4.2 -package ghc -c Test.hs
Found complement!
But with GHC 8.6.3, I get:
$ ghc-8.6.3 --make -package ghc -c TestPlugin.hs
[1 of 1] Compiling TestPlugin ( TestPlugin.hs, TestPlugin.o )
$ ghc-8.6.3 -package ghc -c Test.hs
ghc: panic! (the 'impossible' happened)
(GHC version 8.6.3 for x86_64-apple-darwin):
Failed to locate complement
The problem goes away if I change Test.hs to:
{-# OPTIONS_GHC -fplugin TestPlugin #-}
import Data.Bits -- Should not be required in the client code!
main :: IO ()
main = return ()
That is, if I explicitly import Data.Bits. But tis is quite undesirable, since Test.hs is client code and the users of the plugin have no reason to import all bunch of modules the plugin might need for its own purposes. (In practice, this would require clients to import a whole bunch of irrelevant modules; quite unworkable and not maintainable.)
I've found the following stack-overflow ticket, which seems to suffer from a similar problem: How to replicate the behaviour of 'name in a TH splice However, the answer suggested there is just not OK in this case (and perhaps wasn't really OK there either) since it would require unnecessary changes to client code in my case that is just not reasonable to expect. (Perhaps #JoachimBretner has an idea?) I've also filed this as a GHC ticket (https://ghc.haskell.org/trac/ghc/ticket/16104#ticket), but feedback from the stack-overflow community is greatly appreciated.
Should I be coding my plugin differently? Or is this a GHC regression?
Not a direct answer, but when I need to “hard-code” a name in a GHC plugin, I don’t use TH. Instead, I use findImportedModule and lookupOrig to look it up, e.g. as in
lookupJDITyCon :: TcPluginM Class
lookupJDITyCon = do
Found _ md <- findImportedModule jdiModule Nothing
jdiTcNm <- lookupOrig md (mkTcOcc "JustDoIt")
tcLookupClass jdiTcNm
where
jdiModule = mkModuleName "GHC.JustDoIt"
from the code of my ghc-justdoit plugin.
I use Template Haskell names when the user needs to mention names, e.g. in splices or annotations, that I want to pick up in the plugin. This is what I do in inspection-testing. I discuss this a bit in the appendix of the Inspection Testing paper.

Type mismatch after cabal update?

Program has the following import:
import Pipes.Network.TCP
import Pipes
import Pipes.Core
import qualified Data.ByteString.Char8 as C
Compilation fails like so:
Couldn't match expected type `bytestring-0.9.2.1:Data.ByteString.Internal.ByteString'
with actual type `C.ByteString'
Expected type: Proxy
Int
bytestring-0.9.2.1:Data.ByteString.Internal.ByteString
()
b0
m0
()
Actual type: Proxy Int C.ByteString () C.ByteString IO ()
I can be more specific about the code, but it looks like this is not related to code - rather some cabal whim. Perhaps, Pipes that I import are considered to use a different ByteString than the one imported with qualified name.
The program used to compile some time ago (I have its working executable), but now it stopped, and I suspect there could have been some cabal update or package installation. How to debug and fix this?
Assuming your program is built with cabal, you should re-configure it. This may highlight other problems, such as dependencies which would require re-installing or breaking other parts of the dependency tree. The "old way" to solve this is to progressively cabal install more and more things until the dependency solver agrees it's possible, e.g.
$ cabal install .
# complains that reinstalls might break lens
$ cabal install . lens
# complains that reinstalls might break bytestring
$ cabal install . lens bytestring
# complains that reinstalls might break X
$ cabal install . lens bytestring X
...etc. The "new way" is to use no-reinstall cabal. You will still need to reconfigure before you build, and may need to install some dependencies again to transition properly.

Problems with SourceGraph (Haskell)

I try to visualize an existing Haskell code base with SourceGraph.
SourceGraph mycabal.cabal
But all I get are error messages like this:
Could not parse source file ./src/mysource.hs
SourceGraph: Could not find data file templates/default.html
Any hints what to do or where to look for documentation?
The only documentation I have found so far is this one: http://code.haskell.org/~ivanm/Sample_SourceGraph/SourceGraph/SourceGraph.html which unfortunately only consists of catchy images but with no hints how to produce them.
Regarding your immediate question, it seems like the best documentation here is the source: http://code.haskell.org/SourceGraph/
I tried it on a repository of my own, and ran into the parsing issue, too. This is haskell-src-exts failing to parse a module. The following patch shows the actual error:
--- Parsing.hs 2013-02-14 12:59:34.000000000 +0100
+++ ../SourceGraph-0.7.0.5-fixed/Parsing.hs 2014-04-08 20:49:54.000000000 +0200
## -64,7 +64,7 ##
parseFile :: FileContents -> Either FilePath Module
parseFile (p,f) = case (parseFileContentsWithMode mode f) of
(ParseOk hs) -> Right hs
- _ -> Left p
+ x -> Left $ p ++ ": " ++ show x
where
mode = defaultParseMode { parseFilename = p
, fixities = Nothing
It turns out that most of my failing modules failed because "MultiParamTypeClasses is not enabled". This is apparently haskell-src-exts being rightfully strict, while ghc is happy without the MultiParamTypeClasses extension: https://github.com/haskell-suite/haskell-src-exts/issues/29
So as a quick fix, try adding
{-# LANGUAGE MultiParamTypeClasses #-}
at the top of your failing modules.
Just ran into a similar issue, so I thought I'd document here what I did. I put my changes in a patch file.
https://gist.github.com/ivanperez-keera/b398ce71a22e8a4849f3
cabal sandbox init
cabal unpack SourceGraph
wget https://gist.githubusercontent.com/ivanperez-keera/b398ce71a22e8a4849f3/raw/bf26ffc45564934c0f175e7619ded8a299a9b7d5/verbose-sourcegraph.patch
cd SourceGraph-0.7.0.6/
patch -i ../verbose-sourcegraph.patch
cd ..
cabal install SourceGraph-0.7.0.6/
Most of the "errors" in my files where due to bang patterns and multi param type classes. There must be a better solution to make SourceGraph's parse mode default to the same as GHC.

Snap: Params type error

I get this type error:
Couldn't match type `containers-0.5.0.0:Data.Map.Base.Map
ByteString [ByteString]'
with `M.Map ByteString [ByteString]'
Expected type: M.Map ByteString [ByteString]
Actual type: Params
But Params type is Map ByteString [ByteString]
type Params = Map ByteString [ByteString]
If it is of any help, this is the full function:
import qualified Data.Map as M
categoryDoc :: Params -> Document
categoryDoc params = map (\(k,[v]) -> T.decodeUtf8 k =: T.decodeUtf8 v) $ M.toList params
Thank you.
You have encountered cabal hell.
The problem is that there are multiple versions of the containers package installed. This means that there are two versions of the Map data type, one from containers-0.5.0.0 and one from the other version. Those two won't match, and that's why you get the error.
The easiest solution to that problem is to delete the ~/.ghc (on unix) directory and rebuilt everything. But that won't protect you from such problems in future, and there is also a chance that it won't work at all. So this is not a good solution.
If you have cabal-install of at least version 1.18, you can use the cabal sandboxes feature. This allows you to create an isolated package environment for each project, and thus avoid such conflicts. Just switch to your project and run:
cabal sandbox init # Create a new sandbox
cabal install --only-dependencies # Install dependencies
cabal build # Build your project
You can also use cabal install to install your project into the sandbox or cabal repl to start GHCi with the right settings for your project.
If you do not have a new-enough version of cabal-install and can't upgrade, you can use cabal-dev to create and manage sandboxes.

Resources