Arg
Arg

Reputation: 1916

Parsec and Applicative style

can someone help me to understand how to use Applicative style for writing Parsec parsers? This is the code i have:

module Main where
import Control.Applicative hiding (many)
import Text.Parsec
import Data.Functor.Identity
data Cmd = A | B deriving (Show)

main = do
  line <- getContents
  putStrLn . show $ parseCmd line

parseCmd :: String -> Either ParseError String
parseCmd input =  parse cmdParse "(parser)" input

cmdParse :: Parsec String () String
cmdParse = do
  slash <- char '/'
  whatever <- many alphaNum
  return (slash:whatever)

cmdParse2 :: String -> Parsec String () String
cmdParse2 = (:) <$> (char '/') <*> many alphaNum

but when i try to compile it, i get following:

/home/tomasherman/Desktop/funinthesun.hs:21:13:
    Couldn't match expected type `Parsec String () String'
                with actual type `[a0]'
    Expected type: a0 -> [a0] -> Parsec String () String
      Actual type: a0 -> [a0] -> [a0]
    In the first argument of `(<$>)', namely `(:)'
    In the first argument of `(<*>)', namely `(:) <$> (char '/')'
Failed, modules loaded: none.

The idea is that i want cmdParse2 to do same thing that cmdParse does, but using applicative stuff...my approach is probably completely wrong, i'm new to haskell

Upvotes: 10

Views: 1496

Answers (2)

shang
shang

Reputation: 24802

Your applicative usage is spot on, you just have an incorrect signature. Try:

cmdParse2 :: Parsec String () String

Upvotes: 5

Jan Christiansen
Jan Christiansen

Reputation: 3173

Your approach looks correct to me, the problem is that cmdParse2 has the wrong type. It should have the same type as cmdParse. By the way, you can omit the parens around char '/' in the applicative style parser.

Upvotes: 4

Related Questions