9

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

imz -- Ivan Zakharyaschev
  • 4,921
  • 6
  • 53
  • 104
NerdGGuy
  • 139
  • 1
  • 6

2 Answers2

5

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
AndrewC
  • 32,300
  • 7
  • 79
  • 115
  • Thanks! This works for me. The code does warn about a deprecated function but the answer is what I needed. _Warning: In the use of `B.putStrLn' (imported from Data.ByteString): Deprecated: "Use Data.ByteString.Char8.putStrLn instead_ – NerdGGuy Nov 03 '12 at 02:20
  • 1
    @NerdGGuy Let's get rid of `Data.ByteString` altogether and just use `Data.ByteString.Char8` instead then (see edit). – AndrewC Nov 03 '12 at 03:01
  • Great. Using Data.ByteString.Char8 makes sense to me. – NerdGGuy Nov 03 '12 at 03:43
5

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
John L
  • 27,937
  • 4
  • 73
  • 88
  • do you mean import qualified Data.ByteString as B? Also one more error: Couldn't match expected type `B.ByteString' with actual type `String' Expected type: [B.ByteString] Actual type: [String] In the first argument of `head', namely `args' In the first argument of `makePassword', namely `(head args)' – NerdGGuy Nov 03 '12 at 02:04