Using Criterion in Haskell - haskell

I am very new to Haskell.
I am trying to use Criterion to get performance data. My Main module is as follows:
module Main where
import SingleThreadedBlockChain
import Data.Time.Clock.System (getSystemTime)
import System.IO (readFile)
import System.TimeIt
import System.Environment ( getArgs )
import Criterion.Main
main :: IO ()
main = do
args <- getArgs
time <- getSystemTime
content <- readFile (args !! 0)
defaultMain [
bench "putStrLn" $ nfIO (putStrLn ("The last block is " ++ show (last (makeBlockChain "" (lines content) 0 (show time)))))
]
I am trying to use the Criterion documentation + things I've seen on StackOverflow to get this working. I'm getting the following error:
Error: none of the specified names matches a benchmark
I thought I would be benchmarking IO. From the examples I've seen, the names don't always match the benchmarks. Could someone explain how the names should relate to the benchmarks?

Criterion's defaultMain does its own cli argument parsing. It uses the first argument to try and match a specific benchmark name to run (in your case you only have "putStrLn"). If you want to do your own argument parsing you can change the arguments before passing to defaultMain like this:
args <- getArgs
withArgs (drop 1 args) $ defaultMain ...
This will hide the first argument from defaultMain so you can use it as you please.

Related

how to list the functions exported by a Haskell module from an .hs script?

I am aware of this thread and the agreed-upon ghci :browse command, but I am looking for something similar to run from a script.hs file:
Say I have a module that I can import into my script.hs. How do I then view the list of functions I have just gained access to?
What I've settled on for now
Adapting this thread that suggests the now-deprecated ghc-mod command-line program, I am
calling the terminal command ghc -e ':browse <module, e.g. Data.List>'
from my script.hs using Shelly.
My full script:
#!/usr/bin/env runghc
{-# LANGUAGE OverloadedStrings #-}
import Safe (headDef)
import Shelly
import System.Environment (getArgs)
import qualified Data.Text as T
mdl :: IO String
mdl = getArgs >>= return . headDef "Data.List"
runShelly :: String -> IO ()
runShelly mdl = shelly $ silently $ do
out <- run "ghc" ["-e", T.pack (":browse " ++ mdl)]
let lns = T.lines out
liftIO $ mapM_ (putStrLn .T.unpack) $ lns
main :: IO ()
main = mdl >>= runShelly
This way I can pass the module name on the command line as <script> <module> and get back the functions, one per line. It defaults to Data.List if I pass no arguments.
So that's a solution, but surely there must be handier introspection facilities than this?

Input arguments using getArgs returns nothing

I am trying to understand getArgs but I am getting a weird behavior that I am not understanding. Here is my program:
getMyArgs :: IO [String]
getMyArgs =do
x <- getArgs
return x
I run this and get:
*Main> hello <- getMyArgs
*Main>
Why doesn't it return my argument passed? I tried to put in a " show() " but that turns it into a String instead of a [String]
getMyArgs :: IO [String]
getMyArgs =do
x <- getArgs
return x
The do notation desugars to:
getMyArgs :: IO [String]
getMyArgs = getArgs >>= \x -> return x
Using the right identity we can rewrite this to:
getMyArgs :: IO [String]
getMyArgs = getArgs
So you've just defined a new name for getArgs. Now why does getArgs not show your program arguments? Well it appears you didn't provide any program arguments. In the interpreter it can be tricky to provide arguments - one way is to :set them:
Prelude> :set args hello world
Prelude> import System.Environment
Prelude System.Environment> getArgs
["hello","world"]
EDIT: Oh you might be looking to print the value you bound. Consider:
Prelude System.Environment> hello <- getArgs
Prelude System.Environment> print hello
["hello","world"]
Thanks to #4castle for this observation.
Assume your Haskell program is compiled to an executable foo. When you call your program, you want to pass some runtime arguments to your program eg foo param1 param2 . Depending on the values of param1 and param2 you will take different actions in your program.
Now with the getArgs function you get access to these parameters in your Haskell program.
In GHCi this argument passing can be simulated. Either with the :set args paarm1 param2 command as shown in the answer of Thomas M. DuBuisson
or you call your main program in GHCI with :main param1 param2 .
In both scenarios getEnv will return IO ["param1", "param2"]

Haskell: parse error on input `import'

I am trying to recreate the output of this Haskell code:
forM_ = flip mapM_
import Control.Monad.Cont
main = do
forM_ [1..3] $ \i -> do
print i
forM_ [7..9] $ \j -> do
print j
withBreak $ \break ->
forM_ [1..] $ \_ -> do
p "loop"
break ()
where
withBreak = (`runContT` return) . callCC
p = liftIO . putStrLn
The expected output is as follows:
$ runhaskell for.hs
1
2
3
7
8
9
loop
But I am getting the following error:
Test4.hs:2:1: parse error on input `import'
Any ideas about what is going wrong?
Test4.hs:2:1: parse error on input `import'
The error points to the second line of your file. Quoting the first two lines:
forM_ = flip mapM_
import Control.Monad.Cont
The problem is that an import declaration must be at the beginning of a module, before any definitions (the only things that can come before an import are language pragmas, such as those used to enable GHC extensions, and the module declaration). In your case, the first line of the file is a definition, and so the misplaced import declaration in the second line leads to a parse error. Since that first line wasn't actually part of the code snippet in the post you linked to, you can simply delete it.

How do I putStrLn a Data.ByteString.Internal.ByteString?

I'm learning haskell and decided to try writing some small test programs to get use to Haskell code and using modules. Currently I'm trying to use the first argument to create a password hash using the Cypto.PasswordStore. To test out my program I'm trying to create a hash from the first argument and then print the hash to screen.
import Crypto.PasswordStore
import System.Environment
main = do
args <- getArgs
putStrLn (makePassword (head args) 12)
I'm getting the following error:
testmakePassword.hs:8:19:
Couldn't match expected type `String'
with actual type `IO Data.ByteString.Internal.ByteString'
In the return type of a call of `makePassword'
In the first argument of `putStrLn', namely
`(makePassword (head args) 12)'
In a stmt of a 'do' block: putStrLn (makePassword (head args) 12)
I've been using the following links as references but I am now just trial-erroring to no avail.
http://hackage.haskell.org/packages/archive/bytestring/0.9.0.4/doc/html/Data-ByteString-Internal.html
http://hackage.haskell.org/packages/archive/pwstore-purehaskell/2.1/doc/html/Crypto-PasswordStore.html
You haven't imported ByteString, so it's trying to use the String version of putStrLn.
I've provided toBS for the String->ByteString conversion.
Try
import Crypto.PasswordStore
import System.Environment
import qualified Data.ByteString.Char8 as B
toBS = B.pack
main = do
args <- getArgs
makePassword (toBS (head args)) 12 >>= B.putStrLn
You have to do two things differently. First, makePassword is in IO, so you need to bind the result to a name and then pass the name to the IO function. Secondly, you need to import IO functions from Data.ByteString
import Crypto.PasswordStore
import System.Environment
import qualified Data.ByteString as B
main = do
args <- getArgs
pwd <- makePassword (B.pack $ head args) 12
B.putStrLn pwd
Or, if you won't be using the password result anywhere else, you can use bind to connect the two functions directly:
main = do
args <- getArgs
B.putStrLn =<< makePassword (B.pack $ head args) 12

getting the program arguments

I need to get program arguments and show them
module Main ( main ) where
import System ( getArgs )
main = do
args<-getArgs
print $ show args
But it does nothing.Maybe my call incorrect?
>main 3 4
It sounds like you're trying to run the program from within GHCi. In that case, you can use the :main command to run your program with arguments.
*Main> :main foo bar
"[\"foo\",\"bar\"]"
Try changing 'System' -> 'System.Environment':
module Main ( main ) where
import System.Environment ( getArgs )
main = do
args <- getArgs
mapM putStrLn args

Resources