If you have a shell script like
#!/bin/bash
foo() {
echo "foo"
}
you can use the readCreateProcess function from the process package to source the script and execute the function in one go, like this:
module Main where
import System.Process
main :: IO ()
main = do
-- I had to put the full path of the script for it to work
result <- readCreateProcess ((shell ". /tmp/foo.sh && foo")) ""
print result
This solution assumes that the script only does things like defining functions and setting environment variables, without running undesired "effectful" code each time it is sourced.