Search code examples
shellhaskellheredocrunhaskell

Is it possible to pass arguments to `runhaskell` using a Heredoc?


I would like to pass the string "Hello World" to the following Haskell script:

main :: IO ()
main = interact id

that sits inside a Heredoc. Is that possible ?

I have made a minimal reproducible example (does not currently work):

#!/bin/bash
echo "Hello World" | runhaskell <<HASKELL_END 2>/dev/null
main :: IO ()
main = interact id

Solution

  • You can do it if it's okay for you to use zsh.

    #!/bin/zsh
    echo "Hello World" | runghc =(cat <<'HASKELL_END'
    main :: IO ()
    main = interact id
    HASKELL_END
    )
    

    or

    #!/bin/zsh
    echo "Hello World" | runghc =(<<<'
    main :: IO ()
    main = interact id'
    )
    

    The thing is, you need to pass your source code as a file since interact closes stdin. Unfortunately, process substitution in bash doesn't work well since ghc tries to get a size of the named pipe.

    So this doesn't work.

    #!/bin/bash
    echo "Hello World" | runghc <(cat <<HASKELL_END
    main :: IO ()
    main = interact id
    HASKELL_END
    )
    

    It gives this error.

    *** Exception: /dev/fd/63: hFileSize: inappropriate type (not a regular file)
    

    Of course, you can create a temporary file and delete it manually just like (= ) does internally.