Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 628
Arg Avatar asked Oct 25 '12 09:10

Arg


2 Answers

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

cmdParse2 :: Parsec String () String
like image 154
shang Avatar answered Sep 24 '22 03:09

shang


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.

like image 25
Jan Christiansen Avatar answered Sep 24 '22 03:09

Jan Christiansen