Wizek
Wizek

Reputation: 4993

How to execute Haskell code in the context of Main with `stack`?

I'm looking to do something like this

$ stack eval 'functionDefinedInMain $ 1 + 1' > test1.txt

However, when I execute that, stderr tells me

<interactive>:1:1: Not in scope: ‘functionDefinedInMain’

I've also tried to pipe code into stack ghci, which gets me closer:

$ echo 'functionDefinedInMain $ 1+1' | stack ghci > test2.txt
Using main module: 1. Package `exp-proj' component exe:exp-proj with main-is file: /home/wizek/sandbox/exp-proj/exp-proj/src/Main.hs
Configuring GHCi with the following packages: exp-proj

$ cat test2.txt
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
[1 of 5] Compiling Utils            ( /home/wizek/sandbox/exp-proj/exp-proj/src/Utils.hs, interpreted )
[2 of 5] Compiling Vertex           ( /home/wizek/sandbox/exp-proj/exp-proj/src/Vertex.hs, interpreted )
[3 of 5] Compiling Edge             ( /home/wizek/sandbox/exp-proj/exp-proj/src/Edge.hs, interpreted )
[4 of 5] Compiling Lib              ( /home/wizek/sandbox/exp-proj/exp-proj/src/Lib.hs, interpreted )
[5 of 5] Compiling Main             ( /home/wizek/sandbox/exp-proj/exp-proj/src/Main.hs, interpreted )
Ok, modules loaded: Utils, Vertex, Edge, Lib, Main.
*Main Edge Lib Utils Vertex> 3
*Main Edge Lib Utils Vertex> Leaving GHCi.

As you can see, the output (which is just the number 3 in this example) file is polluted by GHCi.

I'd like the content of the file to be instead:

$ cat test2.txt
3

How can I either

  1. load all my project modules with stack eval as specified in my .cabal file to execute code in context, or
  2. suppress GHCi output to stdout? (I don't mind if GHCi puts messages on stderr)

$ stack --version
Version 1.0.2, Git revision fa09a980d8bb3df88b2a9193cd9bf84cc6c419b3 (3084 commits) x86_64

edit: Added unix and bash tags since it might be possible to achieve this by piping together different stack/GHCi commands even without explicit support from stack.

Upvotes: 1

Views: 628

Answers (2)

Zeta
Zeta

Reputation: 105876

The -e flag in ghc -e expects a Haskell expression and has—by default—only access on Prelude. You need to use additional functions fully qualified:

stack eval 'Library.someFunc $ 1+1'
            ^^^^^^^^

However, this does only work in the following circumstances:

  1. The module must be part of your library, not your executable.
  2. The expression must be exported from the module.

If you're just trying to use Main.xxx, make sure that Main is a visible module in your library. This also concludes that you cannot use eval for executable only projects. However, this can lead to strange problems. For example, GHCi will try to import Main twice, once via the executable and once via the library.

Example

$ stack new exp-eval simple
$ cd exp-eval
$ cat addition >> exp-eval.cabal
$ stack eval 'Main.main'

Where addition has the following content:

library
  hs-source-dirs:      src 
  exposed-modules:     Main
  default-language:    Haskell2010
  build-depends:       base >= 4.7 && < 5 

Upvotes: 3

epsilonhalbe
epsilonhalbe

Reputation: 15967

I don't quite get what you want to do - do you want to execute the main - then use

$> stack runghc ./src/Main.hs > test.txt

or

$> stack build
$> stack exec -- modulename > test.txt

to invoke the compiled binary.

If you have a function that is exported in main it is easiest to use stack ghci and call the function from inside - if it produces a String you can then use

writeFile "test.txt" (myfunction parameter1 parameter2)

to get the desired result.


I have not used stack eval before but I guess you have to export your function in a library for that, I guess your cabal file says that you have only an export of an executable - to give you more info I would need your cabal file.

Upvotes: 0

Related Questions