I'm attempting to add a title to a plot made with Gnuplot in Haskell. While the program produces a graph in a stand-alone window it creates, I can't seem to get it to respond to the title function. Am I using the title function incorrectly?
I'm using Stack, with
- only "-gnuplot" added to the "dependencies:" section of package.yaml
- resolver: lts-15.7 in an unmodified stack.yaml.
on a computer running Linux Mint 19. The code and a screen shot of the pop-up window are:
module Main where
import Graphics.Gnuplot.Advanced
import Graphics.Gnuplot.Plot.TwoDimensional as P2D
import Graphics.Gnuplot.Graph.TwoDimensional as G2D
import Graphics.Gnuplot.Terminal.X11 as X11
zeroToTen = [0.0, 0.1 .. 10.0 :: Double]
main :: IO ()
main = do
plot (X11.title "My Title" X11.cons) (P2D.function G2D.lines zeroToTen sin)
_ <- getLine
return ()
This is a bug in gnuplot (the package). The following is the code block where the options for an X11 terminal are built into gnuplot
-parseable command-line parameters:
File: X11.hs
-- Part of a record update, hence the trailing comma
Terminal.options =
"x11" :
catMaybes (
(fmap quote $ title_ term) :
(fmap (formatBool "persist") $ persist_ term) :
[]),
On the third last line, the title_ :: Maybe String
field of the term
record is surrounded by quotes by the quote
function (just an alias of show
). The issue is that in order to be parsed by gnuplot
, it should also be prepended with title
(see manual). Until it gets fixed, you can always configure gnuplot as a local package and build it from there.
Here is the fix (line 43 of X11.hs):
(fmap (("title " ++) . quote) $ title_ term) :
By the way, there is a more optimal way to import packages. Writing import X as Y
means: "import everything into the global namespace, but also give me Y as an alias for the imported symbols". A better way is import qualified X as Y
, which fences the imported module into the Y
namespace.
Final note
If you try and build gnuplot on your own, you'll find that gnuplot
doesn't compile because of a couple of missing Semigroup
instances caused by the "Semigroup-Monoid" proposal in GHC 8.4. The way to fix this is simply to add a Semigroup
instance that refers to the mappend
method from the Monoid
instance:
import Data.Semigroup
instance Semigroup Script where
(<>) = mappend
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With