I am beginner, so please bear with me.
I have a following code:
{-# LANGUAGE OverloadedStrings #-}
module Lib where
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Data.Monoid ((<>))
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Test.WebDriver
--import Web.Scotty
import Web.Scotty.Trans
firefoxConfig :: WDConfig
firefoxConfig = defaultConfig
startMyBrowser :: WD a -> IO a
startMyBrowser = runSession firefoxConfig
stopMyBrowser = closeSession
someFunc :: WD String
someFunc = do
openPage "http://maslo.cz"
captionElem <- findElem (ByCSS "h2")
text <- getText captionElem
return $ T.unpack text
helloAction :: ActionT TL.Text WD ()
helloAction = do
a <- lift someFunc
text $ "got this for you: " <> TL.pack a
routes :: ScottyT TL.Text WD ()
routes = get "/hello" helloAction
startServer = startMyBrowser $ do
lift $ scottyT 3000 _ routes
stopMyBrowser
I am not sure if even those filled parts are right - it is supposed to start a Selenium session (startMyBrowser), spin up a web server (the scottyT part) and after web server stops it should end the Selenium session (stopMyBrowser).
After fiddling with types I got to that code above and it seems that I only miss one piece - the hole.
Please, if you make it working, try to explain your solution and/or add some links to more materials. I would love to understand those damned transformers.
Edit 1:
Here are the errors:
• Couldn't match type ‘t0 m0’ with ‘WD’
Expected type: WD ()
Actual type: t0 m0 ()
• In a stmt of a 'do' block: lift $ scottyT 3000 _ routes
In the second argument of ‘($)’, namely
‘do { lift $ scottyT 3000 _ routes;
stopMyBrowser }’
In the expression:
startMyBrowser
$ do { lift $ scottyT 3000 _ routes;
stopMyBrowser }
• Found hole:
_ :: WD wai-3.2.1.1:Network.Wai.Internal.Response
-> IO wai-3.2.1.1:Network.Wai.Internal.Response
• In the second argument of ‘scottyT’, namely ‘_’
In the second argument of ‘($)’, namely ‘scottyT 3000 _ routes’
In a stmt of a 'do' block: lift $ scottyT 3000 _ routes
• Relevant bindings include
startServer :: IO () (bound at src/Lib.hs:37:1)
Kind guy ForTheFunctionGod on reddit answered it, here it is:
There's your problem:
lift $ scottyT 3000 _ routes
Since the return type of scottyT is
MonadIO n => n
You don't need to lift it - it can fit into any monad that can perform IO actions. WD is such a monad - note its MonadIO instance. You'd only need to lift scottyT if its return type would be a simple IO.
Type classes like MonadIO, MonadState, etc. mostly obviate the need to manually lift computations. Whereas you'd need to lift a function to type IO Int if you wanted to embed it into StateT s IO Int, you wouldn't need to lift a function of type MonadIO m => m a, because StateT s IO already is an instance of MonadIO, so m can be instantiated to it.
As for the hole: it has to be of type
WD Response -> IO Response
The only way to make this work is to use runSession or one of its friends. I don't know Selenium that well, but, presumably, you can re-use your already opened session's id:
runWD :: WDSession -> WD a -> IO a
startServer = startMyBrowser $ do
sessionID <- getSession
scottyT 3000 (runWD sessionID) routes
stopMyBrowser
I haven't tried this out, but the types should check out. I hope it helps!
It definitely did :).
Related
Is there some module in the Idris standard library (or a third party library) that allows one to shell out to another program? I'm thinking of modules like Python's subprocess and Haskell's System.Process.
Ideally, I'd like to interact programmatically with the process (writing to its stdin, reading from its stdout, etc.).
There is the system : String -> IO Int function which takes a shell command, runs it, and returns its exit code. You'll need to import System to use it:
import System
main : IO ()
main = do
exitCode <- system "echo HelloWorld!"
putStrLn $ "Exit code: " ++ show exitCode
exitCode <- system "echo HelloWorld!; false"
putStrLn $ "Exit code: " ++ show exitCode
On my system the above code results in the following output:
HelloWorld!
Exit code: 0
HelloWorld!
Exit code: 256
I'd expect it to return 1 instead of 256 in the second case. At least it's what echo $? shows.
Another version can be made basing on the Effects library, which is described in this tutorial:
import Effects
import Effect.System
import Effect.StdIO
execAndPrint : (cmd : String) -> Eff () [STDIO, SYSTEM]
execAndPrint cmd = do
exitCode <- system cmd
putStrLn $ "Exit code: " ++ show exitCode
script : Eff () [STDIO, SYSTEM]
script = do
execAndPrint "echo HelloWorld!"
execAndPrint "sh -c \"echo HelloWorld!; exit 1\""
main : IO ()
main = run script
Here we need to explain to Idris that it needs the Effects package:
idris -p effects <filename.idr>
I'm not aware of any Idris library that lets you easily work with stdin/stdout of a subprocess. As a workaround we can use the pipes facilities of C, utilizing its popen / pclose functions, which aready have bindings in the Idris standard library.
Let me show how we could, for example, read from stdout of a subprocess (please bear in mind that it's a simple snippet with rudimentary error processing):
import System
-- read the contents of a file
readFileH : (fileHandle : File) -> IO String
readFileH h = loop ""
where
loop acc = do
if !(fEOF h) then pure acc
else do
Right l <- fGetLine h | Left err => pure acc
loop (acc ++ l)
execAndReadOutput : (cmd : String) -> IO String
execAndReadOutput cmd = do
Right fh <- popen cmd Read | Left err => pure ""
contents <- readFileH fh
pclose fh
pure contents
main : IO ()
main = do
out <- (execAndReadOutput "echo \"Captured output\"")
putStrLn "Here is what we got:"
putStr out
When you run the program, you should see
Here is what we got:
Captured output
I have been trying to get some basic dynamic code compilation working using the GHC API by following a tutorial found here.
This code:
import GHC
import GHC.Paths
import DynFlags
import Unsafe.Coerce
main :: IO ()
main =
defaultErrorHandler defaultDynFlags $ do
func <- runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
setSessionDynFlags dflags
target <- guessTarget "Test.hs" Nothing
addTarget target
r <- load LoadAllTargets
case r of
Failed -> error "Compilation failed"
Succeeded -> do
m <- findModule (mkModuleName "Test") Nothing
setContext [] [m]
value <- compileExpr ("Test.print")
do let value' = (unsafeCoerce value) :: String -> IO ()
return value'
func "Hello"
return ()
Should get the print function from another file called Test.hs, load it and run its print function.
I compile the code with ghc version 7.4.1 using the command:
ghc -package ghc --make Api.hs
But receive the following error:
Api.hs:8:25:
Couldn't match expected type `Severity' with actual type `Settings'
Expected type: LogAction
Actual type: Settings -> DynFlags
In the first argument of `defaultErrorHandler', namely
`defaultDynFlags'
In the expression: defaultErrorHandler defaultDynFlags
What am I doing wrong? I have checked the GHC API docs but am not well versed enough in this kind of thing to understand most of it.
The tutorial is out of date. In ghc-7.0.* and previous, the type of defaultErorHandler was
defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => DynFlags -> m a -> m a
and defaultDynFlags was just a value.
As of ghc-7.2.*, the type of defaultErrorHandler is
defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => LogAction -> m a -> m a
defaultDynFlags is a function
defaultDynFlags :: Settings -> DynFlags
and LogAction is a synonym
type LogAction = Severity -> SrcSpan -> PprStyle -> Message -> IO ()
In 7.6, it has changed again, we now have
defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => FatalMessager -> FlushOut -> m a -> m a
with
type FatalMessager = String -> IO ()
and FlushOut being a newtype wrapper around IO ().
I'm not very familiar with the GHC Api (a too fast-moving target for me), so I'm not sure how the working code should look like, but for the 7.2 and 7.4 series, the first argument to defaultErrorHandler should probably be defaultLogAction.
Also the type of setContext has changed, I don't know if what I have does what you want, but it compiles (with 7.4.2; but you also need the ghc-paths package in addition to ghc for the GHC.Paths module) - I haven't tried to run it, though.
import GHC
import GHC.Paths
import DynFlags
import Unsafe.Coerce
main :: IO ()
main =
defaultErrorHandler defaultLogAction $ do
func <- runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
setSessionDynFlags dflags
target <- guessTarget "Test.hs" Nothing
addTarget target
r <- load LoadAllTargets
case r of
Failed -> error "Compilation failed"
Succeeded -> do
m <- findModule (mkModuleName "Test") Nothing
setContext [IIModule m]
value <- compileExpr ("Test.print")
do let value' = (unsafeCoerce value) :: String -> IO ()
return value'
func "Hello"
return ()
Here is a complete example for dynamic loading, also hosted here:
DynLoad.hs
-----------------------------------------------------------------------------
-- | Example for loading Haskell source code dynamically using the GHC api
-- Useful links:
-- GHC api:
-- http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html
-- Wiki:
-- http://www.haskell.org/haskellwiki/GHC/As_a_library
-----------------------------------------------------------------------------
module DynLoad where
import GHC
import GhcMonad (liftIO)
import GHC.Paths (libdir)
import Name (getOccString)
import Data.Dynamic (fromDyn)
-- | List all exports of this module
-- and evaluate a symbol from a module DynTest
main =
runGhc (Just libdir) $ do
putString ":::Display exports of modules:::"
modSums <- initSession ["DynLoad","DynTest"]
let thisModSum = head modSums
exports <- listExports thisModSum
mapM_ putString exports
putString ":::Evaluate a name from module DynTest:::"
importDecl_RdrName <- parseImportDecl "import DynTest as D"
setContext [IIDecl importDecl_RdrName]
dynVal <- dynCompileExpr "D.aString"
liftIO $ print $ (fromDyn dynVal "nope-nothing")
-- | Init interactive session and load modules
initSession modStrNames = do
dflags <- getSessionDynFlags
setSessionDynFlags $ dflags {
hscTarget = HscInterpreted
, ghcLink = LinkInMemory
}
targets <- mapM
(\modStrName -> do
putString modStrName
target <- guessTarget ("*"++modStrName++".hs") Nothing
return target
) modStrNames
setTargets targets
load LoadAllTargets
modSums <- mapM
(\modStrName -> do
putString modStrName
modSum <- getModSummary $ mkModuleName modStrName
return $ ms_mod modSum
) modStrNames
return modSums
-- | List exported names of this or a sibling module
listExports mod = do
maybeModInfo <- getModuleInfo mod
case maybeModInfo of
(Just modInfo) -> do
let expNames = modInfoExports modInfo
expStrNames = map getOccString expNames
return expStrNames
_ -> return []
-- | Util for printing
putString = liftIO . putStrLn
And here is an example file to load:
DynTest.hs
module DynTest where
aString = "Hello"
The c++ code which i wanted to rewrite or convert is:
class numberClass
{
private:
int value;
public:
int read()
{
return value;
}
void load(int x)
{
value = x;
}
void increment()
{
value= value +1;
}
};
int main()
{
numberClass num;
num.load(5);
int x=num.read();
cout<<x<<endl;
num.increment();
x=num.read();
cout<<x;
}
I do not know how to make any entity(like variable in C++) that can hold value throughout the program in haskell.
Please help.
Thanks
Basically, you can't. Values are immutable, and Haskell has no variables in the sense of boxes where you store values, like C++ and similar. You can do something similar using IORefs (which are boxes you can store values in), but it's almost always a wrong design to use them.
Haskell is a very different programming language, it's not a good idea to try to translate code from a language like C, C++, Java or so to Haskell. One has to view the tasks from different angles and approach it in a different way.
That being said:
module Main (main) where
import Data.IORef
main :: IO ()
main = do
num <- newIORef 5 :: IO (IORef Int)
x <- readIORef num
print x
modifyIORef num (+1)
x <- readIORef num
print x
Well, assuming that it's the wrapping, not the mutability, you can easily have a type that only allows constructing constant values and incrementation:
module Incr (Incr, incr, fromIncr, toIncr) where
newtype Incr a = Incr a deriving (Read, Show)
fromIncr :: Incr a -> a
fromIncr (Incr x) = x
incr :: (Enum a) => Incr a -> Incr a
incr (Incr x) = Incr (succ x)
toIncr :: a -> Incr a
toIncr = Incr
As Daniel pointed out, mutability is out of the question, but another purpose of your class is encapsulation, which this module provides just like the C++ class. Of course to a Haskell programmer, this module might not seem very useful, but perhaps you have use cases in mind, where you want to statically prevent library users from using regular addition or multiplication.
A direct translation of your code to haskell is rather stupid but of course possible (as shown in Daniel's answer).
Usually when you are working with state in haskell you might be able to work with the State Monad. As long as you are executing inside the State Monad you can query and update your state. If you want to be able to do some IO in addition (as in your example), you need to stack your State Monad on top of IO.
Using this approach your code might look like this:
import Control.Monad.State
import Prelude hiding(read)
increment = modify (+1)
load = put
read = get
normal :: StateT Int IO ()
normal = do
load 5
x <- read
lift (print x)
increment
x <- read
lift (print x)
main = evalStateT normal 0
But here you don't have an explicit type for your numberClass. If you want this there is a nice library on hackage that you could use: data-lenses.
Using lenses the code might be a little closer to your C++ version:
{-# LANGUAGE TemplateHaskell #-}
import Control.Monad.State(StateT,evalStateT,lift)
import Prelude hiding(read)
import Data.Lens.Lazy((~=),access,(%=))
import Data.Lens.Template(makeLenses)
data Number = Number {
_value :: Int
} deriving (Show)
$( makeLenses [''Number] )
increment = value %= succ
load x = value ~= x
read = access value
withLens :: StateT Number IO ()
withLens = do
load 5
x <- read
lift $ print x
increment
x <- read
lift $ print x
main = evalStateT withLens (Number 0)
Still not exactly your code...but well, it's haskell and not yet another OO-language.
Working through Real World Haskell right now. Here's a solution to a very early exercise in the book:
-- | 4) Counts the number of characters in a file
numCharactersInFile :: FilePath -> IO Int
numCharactersInFile fileName = do
contents <- readFile fileName
return (length contents)
My question is: How would you test this function? Is there a way to make a "mock" input instead of actually needing to interact with the file system to test it out? Haskell places such an emphasis on pure functions that I have to imagine that this is easy to do.
You can make your code testable by using a type-class-constrained type variable instead of IO.
First, let's get the imports out of the way.
{-# LANGUAGE FlexibleInstances #-}
import qualified Prelude
import Prelude hiding(readFile)
import Control.Monad.State
The code we want to test:
class Monad m => FSMonad m where
readFile :: FilePath -> m String
-- | 4) Counts the number of characters in a file
numCharactersInFile :: FSMonad m => FilePath -> m Int
numCharactersInFile fileName = do
contents <- readFile fileName
return (length contents)
Later, we can run it:
instance FSMonad IO where
readFile = Prelude.readFile
And test it too:
data MockFS = SingleFile FilePath String
instance FSMonad (State MockFS) where
-- ^ Reader would be enough in this particular case though
readFile pathRequested = do
(SingleFile pathExisting contents) <- get
if pathExisting == pathRequested
then return contents
else fail "file not found"
testNumCharactersInFile :: Bool
testNumCharactersInFile =
evalState
(numCharactersInFile "test.txt")
(SingleFile "test.txt" "hello world")
== 11
This way your code under test needs very little modification.
As Alexander Poluektov already pointed out, the code you are trying to test can easily be separated into a pure and an impure part.
Nevertheless I think it is good to know how to test such impure functions in haskell.
The usual approach to testing in haskell is to use quickcheck and that's what I also tend to use for impure code.
Here is an example of how you might achieve what you are trying to do which gives you kind of a mock behavior * :
import Test.QuickCheck
import Test.QuickCheck.Monadic(monadicIO,run,assert)
import System.Directory(removeFile,getTemporaryDirectory)
import System.IO
import Control.Exception(finally,bracket)
numCharactersInFile :: FilePath -> IO Int
numCharactersInFile fileName = do
contents <- readFile fileName
return (length contents)
Now provide an alternative function (Testing against a model):
numAlternative :: FilePath -> IO Integer
numAlternative p = bracket (openFile p ReadMode) hClose hFileSize
Provide an Arbitrary instance for the test environment:
data TestFile = TestFile String deriving (Eq,Ord,Show)
instance Arbitrary TestFile where
arbitrary = do
n <- choose (0,2000)
testString <- vectorOf n $ elements ['a'..'z']
return $ TestFile testString
Property testing against the model (using quickcheck for monadic code):
prop_charsInFile (TestFile string) =
length string > 0 ==> monadicIO $ do
(res,alternative) <- run $ createTmpFile string $
\p h -> do
alternative <- numAlternative p
testRes <- numCharactersInFile p
return (testRes,alternative)
assert $ res == fromInteger alternative
And a little helper function:
createTmpFile :: String -> (FilePath -> Handle -> IO a) -> IO a
createTmpFile content func = do
tempdir <- catch getTemporaryDirectory (\_ -> return ".")
(tempfile, temph) <- openTempFile tempdir ""
hPutStr temph content
hFlush temph
hClose temph
finally (func tempfile temph)
(removeFile tempfile)
This will let quickCheck create some random files for you and test your implementation against a model function.
$ quickCheck prop_charsInFile
+++ OK, passed 100 tests.
Of course you could also test some other properties depending on your usecase.
* Note about the my usage of the term mock behavior:
The term mock in the object oriented sense is perhaps not the best here. But what is the intention behind a mock?
It let's you test code that needs access to a resource that usually is
either not available at testing time
or is not easily controllable and thus not easy to verify.
By shifting the responsibility of providing such a resource to quickcheck, it suddenly becomes feasible to provide an environment for the code under test that can be verified after a test run.
Martin Fowler describes this nicely in an article about mocks :
"Mocks are ... objects pre-programmed with expectations which form a specification of the calls they are expected to receive."
For the quickcheck setup I'd say that files generated as input are "pre-programmed" such that we know about their size (== expectation). And then they are verified against our specification (== property).
For that you will need to modify the function such that it becomes:
numCharactersInFile :: (FilePath -> IO String) -> FilePath -> IO Int
numCharactersInFile reader fileName = do
contents <- reader fileName
return (length contents)
Now you can pass any mock function that takes a file path and return IO string such as:
fakeFile :: FilePath -> IO String
fakeFile fileName = return "Fake content"
and pass this function to numCharactersInFile.
The function consists from two parts: impure (reading part content as String) and pure (calculating the length of String).
The impure part cannot be "unit"-tested by definition. The pure part is just call to the library function (and of course you can test it if you want :) ).
So there is nothing to mock and nothing to unit-test in this example.
Put it another way. Consider you have an equal C++ or Java implementation (*): reading content and then calculating its length. What would you really want to mock and what would remain for testing afterwards?
(*) which is of course not the way you will do in C++ or Java, but that's offtopic.
Based on my layman's understanding of Haskell, I've come to the following conclusions:
If a function makes use of the IO monad, mock testing is going to be impossible. Avoid hard-coding the IO monad in your function.
Make a helper version of your function that takes in other functions that may do IO. The result will look like this:
numCharactersInFile' :: Monad m => (FilePath -> m String) -> FilePath -> m Int
numCharactersInFile' f filePath = do
contents <- f filePath
return (length contents)
numCharactersInFile' is now testable with mocks!
mockFileSystem :: FilePath -> Identity String
mockFileSystem "fileName" = return "mock file contents"
Now you can verify that numCharactersInFile' returns the the expected results w/o IO:
18 == (runIdentity . numCharactersInFile' mockFileSystem $ "fileName")
Finally, export a version of your original function signature for use with IO
numCharactersInFile :: IO Int
numCharactersInFile = NumCharactersInFile' readFile
So, at the end of the day, numCharactersInFile' is testable with mocks. numCharactersInFile is just a variation of numCharactersInFile'.
I'm writing some tests using HUnit and I would like to assert that a particular function throws an exception given a certain input. I can't find an assert function which provides the required functionality. Anyone know of a test framework that does?
Although HUnit doesn't come with any exception assertions, it's easy to write your own:
import Control.Exception
import Control.Monad
import Test.HUnit
assertException :: (Exception e, Eq e) => e -> IO a -> IO ()
assertException ex action =
handleJust isWanted (const $ return ()) $ do
action
assertFailure $ "Expected exception: " ++ show ex
where isWanted = guard . (== ex)
testPasses = TestCase $ assertException DivideByZero (evaluate $ 5 `div` 0)
testFails = TestCase $ assertException DivideByZero (evaluate $ 5 `div` 1)
main = runTestTT $ TestList [ testPasses, testFails ]
You can do something more fancy like using a predicate instead of explicit comparison if you like.
$ ./testex
### Failure in: 1
Expected exception: divide by zero
Cases: 2 Tried: 2 Errors: 0 Failures: 1
Note that evaluate here might get optimized away (see GHC ticket #5129), but for testing code in the IO monad this should work fine.
You can use assertRaises from testpack.
hspec (or more precisely hspec-expectations) has shouldThrow.