bashshellcommand-line-argumentsquotesrunhaskell

`runhaskell` can't see packages if the arguments are passed in the form of a variable


Whenever I pass explicit parameters to runhaskell command using a variable, in order to make a specific package visible, for example:

#!/bin/bash
args="'-package pandoc'"

runhaskell --ghc-arg="$args"<<EOF

import Text.Pandoc

main :: IO ()
main = print $ "Hello World"
EOF

I get the error:

: error: Can't find '-package pandoc' *** Exception: ExitFailure 1

However, if I enter the contents of that variable explicitly:

#!/bin/bash

runhaskell --ghc-arg='-package pandoc'<<EOF

import Text.Pandoc

main :: IO ()
main = print $ "Hello World"
EOF

The script works as expected. Does someone know why is this the case ?


Solution

  • You are passing this escaped a second time. You should work with:

    #!/bin/bash
    args="-package pandoc"  # no quotations in the string
    
    runhaskell --ghc-arg="$args"<<EOF
    
    import Text.Pandoc
    
    main :: IO ()
    main = print $ "Hello World"
    EOF
    

    By using "$args" it is already clear that you use this as a single parameter, but if you use single quotes inside the string, these will be passed as content of the parameter. In other words you will call ghc-arg with '-package pandoc' as content of the first argument, where the single quotes are thus not interpreted by the shell, but given to the runhaskell executable. Since this does not start with a hyphen (-) likely the interpreter assumes it is the name of the file to run and not a flag, and thus looks for a file with that name in the working directory.

    You can also pass multiple parameters, without quotes for $args:

    #!/bin/bash
    args="-package=pandoc -package=pandoc-types"  # no quotations in the string
    
    runhaskell -- $args <<EOF
    
    import Text.Pandoc
    
    main :: IO ()
    main = print $ "Hello World"
    EOF
    

    The echo command can for example show the content of the parameter:

    $ echo 'foo'
    foo
    $ echo '"foo"'
    "foo"
    $ echo "foo"
    foo
    $ echo "'foo'"
    'foo'
    

    The "outer" quotes (whether ' or ") are thus interpreted by the shell, but the inner quotes (if present) are passed as parameter value.