0

My goal is to pipe some steps for ghci to run from a bash script and then exit cleanly. The commentary online says to use runhaskell for this.

This is the command I'm trying to run:

ghci> import System.Random 

ghci> random (mkStdGen 100) :: (Int, StdGen) 

With expected result similar to:

(-3633736515773289454,693699796 2103410263)

When I drop this into a file randomtest.hs and execute it with runhaskell I get the following error:.

randomtest.hs:3:1: error:
    Invalid type signature: random (mkStdGen 100) :: ...
    Should be of form <variable> :: <type>

I need a hint to go in the right direction.

My question is: Why does ghci behave differently to runHaskell?

hawkeye
  • 34,745
  • 30
  • 150
  • 304
  • GHCi is a tool for checking how code behaves. GHCi is not a way of running Haskell programs, and should not be treated as such. – AJF Dec 09 '17 at 00:15
  • Do you mean that you want a way of writing a script that, when run, produces a sort of live transcript of what the GHCi session would look like if you were typing the commands manually (with prompts, input, and output all shown)? – K. A. Buhr Dec 09 '17 at 14:48
  • Thanks @K.A.Buhr - I've pushed that issue into another question to make this question more focused. – hawkeye Dec 10 '17 at 02:37
  • Thanks @AJFarmar - that's helpful. – hawkeye Dec 10 '17 at 02:37

1 Answers1

3

ghci is a REPL (Read, Eval, Print Loop). However, runhaskell is nearly the same as compiling a program into an executable, and then running it. GHCI lets us run individual functions and arbitrary expressions, wheras runhaskell just calls the main function and interprets the file, instead of compiling it, and running that.

As @AJFarmar points out, GHCI is best used to debug and test a program you're building, whilst runhaskell is a nice way to run a whole program without having to compile.

So, to fix your issue, we just need to give the program a main function. ghci calls print on the result of every expression which is typed into the interpreter and not bound to a variable.

So, our main function can just be:

main = print (random (mkStdGen 100) :: (Int, StdGen))

We still need to import System.Random, so the whole file becomes:

import System.Random

main = print (random (mkStdGen 100) :: (Int, StdGen))

Then, we can run as expected:

[~]λ runhaskell randomtest.hs 
(-3633736515773289454,693699796 2103410263)

If we want to multiple commands from runhaskell we can just add more to a do block in main:

import System.Random

main = do
    print (random (mkStdGen 100) :: (Int, StdGen))
    let x = 5 * 5
    print x
    putStrLn "Hello world!"
Zpalmtree
  • 1,339
  • 8
  • 14
  • Cool - is there a way to script ghci so it runs from the bash script and exits cleanly? – hawkeye Dec 09 '17 at 00:28
  • @hawkeye Not sure exactly what you're trying to achieve. Ghci isn't really suited to scripting. – Zpalmtree Dec 09 '17 at 00:49
  • You can use `runhaskell` in a shebang. Would an example help? – Thomas M. DuBuisson Dec 09 '17 at 00:59
  • Thanks that's helpful. I'm trying to run some commands from a book repeatably and in sequence, automated from the bash command prompt. Specifically, I'm trying to replicate running some ghci commands in a way that exits cleanly. (Ie not stuck in the ghci REPL). – hawkeye Dec 09 '17 at 01:00
  • @hawkeye You can simply combine your commands in a do block, and then run it with runhaskell, e.g. `main = do print (random (mkStdGen 100) :: (Int, StdGen)); putStrLn "hello!"` (You only need semi colons if you do it on one line, like comments are constrainted to) – Zpalmtree Dec 09 '17 at 01:20