Dynamic code loading w/ Haskell - haskell

I've been playing around with the plugins package. I want a host application to dynamically compile and load Haskell source files in a sandboxed environment. Compilation works just fine. Loading fails as soon as the plugin references modules available in the sandbox only. Here is what I've got for the plugin:
module Plugin (resource) where
import ServerAPI
import System.Plugins -- this module is only available in the sandbox
resource = Interface { action = timesTwo }
timesTwo :: Integer -> IO Integer
timesTwo n = return $ n * 2
Loading the plugin from the host application looks like this:
pkgConfDir = "/home/me/plugins/.cabal-sandbox/x86_64-osx-ghc-7.8.4-packages.conf.d
loadedOk <- pdynload "Plugin.o" ["."] [pkgConfDir] "ServerAPI.Interface" "resource"
This is what I've got in the sandbox:
> cabal sandbox hc-pkg list
…
/home/me/plugins/.cabal-sandbox/x86_64-osx-ghc-7.8.4-packages.conf.d
plugins-1.5.4.0
…
This is what I get when running the host application:
Failed to load interface for ‘System.Plugins.Env’
no package matching ‘plugins-1.5.4.0’ was found
As mentioned above, when I get rid of the import System.Plugins statement in the plugin the code does load. What am I missing?
Edit:
The cabal file:
name: plugins
version: 0.1.0.0
-- synopsis:
-- description:
-- license:
license-file: LICENSE
author: W. Davis
maintainer: w.davis#spam.me.not
-- copyright:
-- category:
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10
executable plugins
main-is: Main.hs
-- other-modules:
-- other-extensions:
build-depends: base >=4.7 && <4.8, plugins >=1.5 && <1.6
-- hs-source-dirs:
default-language: Haskell2010

Related

How do I import a text file in a cabal project?

In app/Main.hs, I want to open a text file, "foo.txt". I know how to open a text file in a plain Haskell program. In my cabal project,
import System.IO
Main = do
contents <- readFile "foo.txt"
print $ Main.lex contents
return contents
type Keyword = String
lex :: String -> [Keyword]
lex "" = []
lex x = words x
gives the error
openFile: does not exist (No such file or directory)
What do I need to change in my cabal file, or the file path or location to be able to open the file? I've tried putting it next to the output binary, and that doesn't work either.
This is my cabal file:
-- This file has been generated from package.yaml by hpack version 0.28.2.
--
-- see: https://github.com/sol/hpack
--
-- hash: baf2fc7e230f4b4937dfd918a13fefb55b66c7a4468b24d0e3e90cad675b26d5
name: CCompiler
version: 0.1.0.0
description: Please see the README on GitHub at <https://github.com/githubuser/CCompiler#readme>
homepage: https://github.com/githubuser/CCompiler#readme
bug-reports: https://github.com/githubuser/CCompiler/issues
author: Author name here
maintainer: example#example.com
copyright: 2018 Author name here
license: BSD3
license-file: LICENSE
build-type: Simple
cabal-version: >= 1.10
extra-source-files:
ChangeLog.md
README.md
source-repository head
type: git
location: https://github.com/githubuser/CCompiler
library
exposed-modules:
Lib
other-modules:
Paths_CCompiler
hs-source-dirs:
src
build-depends:
base >=4.7 && <5
default-language: Haskell2010
executable CCompiler-exe
main-is: Main.hs
other-modules:
Paths_CCompiler
hs-source-dirs:
app
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends:
CCompiler
, base >=4.7 && <5
default-language: Haskell2010
test-suite CCompiler-test
type: exitcode-stdio-1.0
main-is: Spec.hs
other-modules:
Paths_CCompiler
hs-source-dirs:
test
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends:
CCompiler
, base >=4.7 && <5
default-language: Haskell2010
add
data-dir: data
in the top section of the cabal file.
create the directory 'data' next to src and app, and put all files in there.
Make sure your cabal file also has this line
other-modules:
Paths_CCompiler
with your project's name instead of CCompiler.
My main function is now this
module Main where
import Lib
import System.IO
import Paths_CCompiler
main = do
filepath <- getDataFileName "return_2.c"
contents <- readFile filepath
print $ Lib.lex contents
return contents
Thanks to this blog post.
I understand your question to be about finding files at runtime, which you want to process and aren't packaged with your package.
Where are severals ways, how you could find files at runtime, which aren't packaged.
Either add an command line flag and call your executable with the absolute path of the file you want to process.
Or implement a file chooser dialog, with e.g. gi-gtk.
Or hard coding relative paths which isn't advisable, as they are interpreted relative to the current working directory of your process, which can be different, depending on how the program did get started.
If you want to determine, which current working directory your program runs in, if started with cabal run, just do a litte test project with the following cabal file:
name: test2
build-type: Simple
cabal-version: >= 1.10
version: 0.0.0.1
executable test2
hs-source-dirs: .
main-is: test2.hs
build-depends:
base
, directory
and the following test2.hs:
module Main where
import System.Directory
main :: IO ()
main = do
cwd <- getCurrentDirectory
putStrLn cwd

Not in scope: type constructor or class ‘Test.Framework.TestSuite’ when trying to create unit tests

I'm writing a small library in Haskell, and want to have tests to accompany it. For testing I intend to use HFT, and the project as a whole is managed by stack. stack test fails for some reason with the following output:
[1 of 2] Compiling Main ( test/Ini.hs, .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.0.1.0/build/ini-tests/ini-tests-tmp/Main.o ) │····························
[2 of 2] Compiling Paths_schemer ( .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.0.1.0/build/ini-tests/autogen/Paths_schemer.hs, .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.0.1.0/build/ini-tests/ini-tests-tm│····························
p/Paths_schemer.o ) │····························
│····························
/stuff/projects/schemer/.stack-work/dist/x86_64-linux-tinfo6/Cabal-2.0.1.0/build/ini-tests/autogen/Paths_schemer.hs:54:39: error: │····························
Not in scope: type constructor or class ‘Test.Framework.TestSuite’ │····························
No module named ‘Test.Framework’ is imported. │····························
│····························
/stuff/projects/schemer/.stack-work/dist/x86_64-linux-tinfo6/Cabal-2.0.1.0/build/ini-tests/autogen/Paths_schemer.hs:55:38: error: │····························
Not in scope: ‘Test.Framework.makeTestSuite’ │····························
No module named ‘Test.Framework’ is imported. │····························
My Ini.hs file that will later contain the tests is very bare-bone, just
import Test.Framework
main :: IO ()
main = htfMain htf_thisModulesTests
My package.yaml is
name: schemer
version: 0.1.0.0
github: "mpevnev/schemer"
license: BSD3
author: "Michail Pevnev"
maintainer: "mpevnev#gmail.com"
copyright: ""
extra-source-files: []
# Metadata used when publishing your package
# synopsis: Short description of your package
# category: Web
# To avoid duplicated efforts in documentation and dealing with the
# complications of embedding Haddock markup inside cabal files, it is
# common to point users to the README.md file.
description: Please see the README on GitHub at <https://github.com/mpevnev/schemer#readme>
dependencies:
- attoparsec
- base >= 4.7 && < 5
- text
library:
source-dirs: src
tests:
ini-tests:
main: Ini.hs
source-dirs: test
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
- -F
- -pgmF htfpp
dependencies:
- schemer
- text
- HTF
Here's the autogenerated schemer.cabal:
-- This file has been generated from package.yaml by hpack version 0.28.2.
--
-- see: https://github.com/sol/hpack
--
-- hash: 17ae623236b8f5b101f56373c975656e898efa7506acb143db7375f229509a79
name: schemer
version: 0.1.0.0
description: Please see the README on GitHub at <https://github.com/mpevnev/schemer#readme>
homepage: https://github.com/mpevnev/schemer#readme
bug-reports: https://github.com/mpevnev/schemer/issues
author: Michail Pevnev
maintainer: mpevnev#gmail.com
license: BSD3
license-file: LICENSE
build-type: Simple
cabal-version: >= 1.10
source-repository head
type: git
location: https://github.com/mpevnev/schemer
library
exposed-modules:
Control.Scheme.Ini
Control.Schemer
other-modules:
Paths_schemer
hs-source-dirs:
src
build-depends:
attoparsec
, base >=4.7 && <5
, text
default-language: Haskell2010
test-suite ini-tests
type: exitcode-stdio-1.0
main-is: Ini.hs
other-modules:
Paths_schemer
hs-source-dirs:
test
ghc-options: -threaded -rtsopts -with-rtsopts=-N -F -pgmF htfpp
build-depends:
HTF
, attoparsec
, base >=4.7 && <5
, schemer
, text
default-language: Haskell2010
I'm not sure what's wrong and what is this Paths_schemer thing. Help is appreciated.
The options -F -pgmF htfpp are switched on globally. This applies the HTF preprocessor to all the files of the test suite, including the autogenerated Paths_schemer.
The more scalable solution is to enable the preprocessor only on files that import Test.Framework, using the OPTIONS_GHC pragma in each one:
{-# OPTIONS_GHC -F -pgmF htfpp #-}
Another way is to set other-modules: [] in the test-suite section in package.yaml to avoid generating Paths_schemer, although that only solves the problem for this one module.

Haskell Failed to load interface for module

Hello i am trying to use a module inside another module but it seems it just won't work.I tried updating the cabal file,stack,i reinstalled the platform,ghc and everything and it just won't let it import modules.I tried adding in the cabal file both other-modules and home-modules section ..to no effect.What could be the problem?
Modules:
module Test where
test::IO()
test=do
elem<-getLine
print elem
module Main where
import Test
main :: IO ()
main = do
putStrLn "hello world"
Cabal-build renders this error:
$ cabal build
Resolving dependencies...
Configuring console-0.1.0.0...
Warning: To use the 'default-language' field the package needs to specify at
least 'cabal-version: >= 1.10'.
Preprocessing executable 'console' for console-0.1.0.0..
Building executable 'console' for console-0.1.0.0..
<no location info>: warning: [-Wmissing-home-modules]
These modules are needed for compilation but not listed in your .cabal file's other-modules: Test
<no location info>: warning: [-Wmissing-home-modules]
These modules are needed for compilation but not listed in your .cabal file's other-modules: Test
When i build with Stack i get this error:
C:\<path>\Main.hs:4:1: error:
Failed to load interface for `Test'
Use -v to see a list of the files searched for.
Failed, modules loaded: none.
H>>= :module + *Main
Cabal file:
name: console
version: 0.1.0.0
-- synopsis:
-- description:
homepage: https://github.com/githubuser/console#readme
license: BSD3
license-file: LICENSE
author: Bercovici Adrian Simon
maintainer: example#example.com
copyright: 2018 Bercovici Adrian Simon
category: Web
build-type: Simple
cabal-version: >=1.2
extra-source-files: README.md
Executable console
hs-source-dirs: src
main-is: Main.hs
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
other-modules: Test
The other-modules: directive must go inside the Executable console stanza.

Haskell cabal confused about file and module name

In my haskell project, I have the following directory structure (some entries are missing but not relevant to this problem)
- quanthas
- quanthas.cabal
- src/
- QuantHas/
- Settings.hs
My Settings.hs file contains this module header
module QuantHas.Settings(module QuantHas.Settings) where
My cabal file looks like this
Name: QuantHas
Version: 0.0
Description:
QuantHas project is an attempt to port QuantLib to Haskell keeping the functional flavor of Haskell.
License: BSD3
License-file: LICENSE
Build-Type: Simple
Cabal-Version: >=1.10
Library
Build-Depends: base >= 3 && < 5, array >= 0.2
Exposed-modules: QuantHas.Time.Frequency
QuantHas.Time.TimeUnit
QuantHas.Time.Period
QuantHas.Time.Date
QuantHas.Time.DayCounter
QuantHas.Time.BusinessDayConvention
QuantHas.Time.Calendar
QuantHas.Time.Calendars.UnitedKingdom
QuantHas.Time.Schedule
QuantHas.Settings
QuantHas.Require
default-language: Haskell2010
hs-source-dirs: src
-- ghc-options: -Wall
test-suite QuantHas-tests
type: exitcode-stdio-1.0
hs-source-dirs: testsuite
main-is: Tests.hs
default-language: Haskell2010
When I execute
cabal install --enable-tests
I get this message
src/Quanthas/Settings.hs:17:8: error:
File name does not match module name:
Saw: ‘QuantHas.Settings’
Expected: ‘Quanthas.Settings’
This seems wrong. However, what if we do what cabal expects. So the Settings.hs module header now is
module Quanthas.Settings(module Quanthas.Settings) where
Cabal now says
src/QuantHas/Settings.hs:17:8: error:
File name does not match module name:
Saw: ‘Quanthas.Settings’
Expected: ‘QuantHas.Settings’
And it's at this ppint that I give up and turn to SO. Can anyone help me understand what is going on?
Versions info:
Platform: Macbook Pro running MacOS 10.12.3
Haskell: 8.0.1
Cabal: 1.24.0.0
Thanks!
The issue is that there is a typo in one of the import statements in a different module. Since you're on a case-insensitive filesystem (OS X), GHC is able to find the module contents, but upon checking the module header finds it mismatches with the import statement and errors out.

Set up Haskell Project and run tests

I'm trying to set up a Haskell project (library) with tests that I can use to work through The Haskell Road to Logic, Maths, and Programming. There are three parts that I'd like to have:
The code that comes with the book, in a subdirectory
The code I write for exercises in the book; one file per chapter
The code I write for tests; one file per chapter
I have attempted a project setup here, but am getting the following cabal error:
Resolving dependencies...
Configuring haskell-road-0.1.0.0...
Building haskell-road-0.1.0.0...
Failed to install haskell-road-0.1.0.0
Build log ( /Users/stuart/.cabal/logs/haskell-road-0.1.0.0.log ):
cabal: Entering directory '.'
Configuring haskell-road-0.1.0.0...
Building haskell-road-0.1.0.0...
Preprocessing library haskell-road-0.1.0.0...
src/Chapter1.hs:1:1:
File name does not match module name:
Saw: ‘Main’
Expected: ‘Chapter1’
cabal: Leaving directory '.'
cabal: Error: some packages failed to install:
haskell-road-0.1.0.0 failed during the building phase. The exception was:
ExitFailure 1
I'd like to be able to run $ cabal test and have all of the tests run, and have the import paths work. Any help is appreciated. I think there are probably issues with the test structure, but I've had trouble finding definitive guides on the actual setup.
EDIT: More details
src/
Chapter1.hs
Book/
GS.hs
etc....
test/
Chapter1Test.hs
MainTestSuite.hs
TestHelper.hs
haskell-book.hs:
-- Initial haskell-road.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/
-- The name of the package.
name: haskell-road
-- The package version. See the Haskell package versioning policy (PVP)
-- for standards guiding when and how versions should be incremented.
-- https://wiki.haskell.org/Package_versioning_policy
-- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change
version: 0.1.0.0
-- A short (one-line) description of the package.
-- synopsis:
-- A longer description of the package.
-- description:
-- The license under which the package is released.
license: MIT
-- The file containing the license text.
license-file: LICENSE
-- The package author(s).
author: Stuart Terrett
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: shterrett#gmail.com
-- A copyright notice.
-- copyright:
-- category:
build-type: Simple
-- Extra files to be distributed with the package, such as examples or a
-- README.
extra-source-files: ChangeLog.md
-- Constraint on the version of Cabal needed to build this package.
cabal-version: >=1.10
library
-- Modules exported by the library.
exposed-modules: Chapter1, Book.COR, Book.DB, Book.FAIS, Book.FCT, Book.GS, Book.Hierarchy, Book.IAR, Book.Nats, Book.POL, Book.Polynomials, Book.PowerSeries, Book.Query, Book.REL, Book.SetEq, Book.SetOrd, Book.STAL, Book.TAMO, Book.TUOLP, Book.WWN
-- Modules included in this library but not exported.
-- other-modules:
-- LANGUAGE extensions used by modules in this package.
other-extensions: FlexibleInstances
-- Other library packages from which modules are imported.
build-depends: base, random >=1.1 && <1.2, HUnit >=1.3 && <1.4
-- Directories containing source files.
hs-source-dirs: src
-- Base language which the package is written in.
default-language: Haskell2010
test-suite haskell-road-tests
type: exitcode-stdio-1.0
hs-source-dirs: tests, src
main-is: MainTestSuite.hs
build-depends: base,
HUnit,
QuickCheck,
test-framework,
test-framework-hunit,
test-framework-quickcheck2
MainTestSuite.hs
import Chapter1Test
exitProperly :: IO Counts -> IO ()
exitProperly m = do
counts <- m
exitWith $ if failures counts /= 0 || errors counts /= 0 then ExitFailure 1 else ExitSuccess
allTests::[Test]
allTests = [Chapter1Test.itRuns]
main :: IO ()
main = exitProperly (runTestTT (TestList allTests))
Diff of all changes:
http://lpaste.net/5997592404872396800
Specific changes you need to make:
In Chapter1.hs make sure module Chapter1 appears before the import statement:
module Chapter1 where
import ...
In each of the Book modules you need to add the prefix Book. to
each of the module statements, e.g. in Book/COR.hs:
change: module COR
to: module Book.COR
Also, any import statement will also need the Book. prefix, i.e. in Book/STAL.hs:
change: import DB
to: import Book.DB
(It might easier just to leave the book's modules at the top-level of the module name space.)
To fix this compilation error:
src/Book/IAR.hs:131:7:
No instance for (Foldable t3) arising from a use of ‘foldr’
just add {-# LANGUAGE NoMonomorphismRestriction #-} to the top of Book/IAR.hs (it should be the very first line.)
To fix this compilation error:
src/Book/FAIS.hs:14:4: Parse error in pattern: n + 1
change: f (n+1) = True : f n to f n = True : f (n-1).
This is called an n+k pattern and more info about it (and why it has been deprecated) is available here: What are "n+k patterns" and why are they banned from Haskell 2010?
In the test-suite section you have:
hs-source-dirs: tests, src
To use the code in the src directory you tests should depend on the haskell-road library instead of compiling the source code. That is, use these lines in the test-suite section:
hs-source-dirs: tests
build-depends: base, haskell-road, HUnit, ...
File test/Chapter1Test.hs needs a module statement:
module Chapter1Test where
and also fix this import statement:
-import TestHelper.testCase
+import TestHelper (testCase)
File test/MainTestSuite.hs needs these import statements:
import System.Exit
import Test.HUnit
File test/testHelper.hs needs to be renamed to test/TestHelper.hs
and also needs this import statement:
import Test.HUnit
Cabal has
developing packages link and cabal file content structure is described there.
By looking the error message, it seems that your haskell library source file Chapter1 starts with module Main where. It should contain module Chapter1 where, as the error message says.
Libraries should not contain main while the test-executables should, which is why you state in the cabal file the test executables with main-is.
Hope this helps! (I didn't look at the github sources, just the error message.)

Resources