Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6556793
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 25, 20262026-05-25T12:59:24+00:00 2026-05-25T12:59:24+00:00

Working through Real World Haskell right now. Here’s a solution to a very early

  • 0

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.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-25T12:59:25+00:00Added an answer on May 25, 2026 at 12:59 pm

    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).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

While working through Real World Haskell, I tried to complete the palindrome exercise using
So I'm working through some initial chapter exercise of Real World Haskell and I
I'm working through Real World Haskell one of the exercises of chapter 4 is
I'm working through Real World Haskell , and at the moment doing the exercises
I'm a C# developer who is working through Real World Haskell in order to
I'm working through the book Real-World Functional Programming , and I tried to come
Still working through JQuery to get data and repopulate portions of a page. Right
I've been working through Practical Common Lisp and as an exercise decided to write
I'm working on my first real-world Rails project. So far, I'm mostly mashing up
I'm currently working my way through the book Teach Yourself Android Application Development in

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.