Parsing and functor combinator - Haskell

Welcome to the Functional Programming Zulip Chat Archive. You can join the chat here.

Vincent L

Hi, I'm trying to implement a parser in purescript. Currently I have this :

module Main where

import Prelude
import Data.Maybe
import Data.Tuple
import Data.String

import Effect (Effect)
import Effect.Console (log)



newtype Parser a = Parser (String -> Maybe (Tuple a String))

runParser :: forall a. Parser a -> String -> (Maybe (Tuple a String))
runParser (Parser f) = f

instance parserFunctor :: Functor Parser where
  map g parser =
    let
      underTuple (Tuple x y) = Tuple (g x) y
    in
      Parser (\x -> underTuple <$> (runParser parser x))

instance parserApplicative :: Apply Parser where
  apply atob a = Parser applied
    where
      applied content = do
        Tuple f rest <- runParser atob content
        Tuple result rest' <- runParser a rest
        pure $ Tuple (f result) rest'

instance parserMonad :: Bind Parser where
  bind ma atomb = Parser bound
    where
      bound str = do
        Tuple x rest <- runParser ma str
        runParser (atomb x) rest

charParser :: Parser CodePoint
charParser = Parser (\str -> trafficateUncons <$> (uncons str))
  where
    trafficateUncons :: { head::CodePoint, tail::String} -> Tuple CodePoint String
    trafficateUncons { head, tail} = Tuple head tail

specificCharParser :: Char -> Parser Unit
specificCharParser cp = Parser specificCharChecker
  where
    specificCharChecker :: String -> (Maybe (Tuple Unit String))
    specificCharChecker str = do
      Tuple head tail <- runParser charParser str
      if head == (codePointFromChar cp)
        then pure $ Tuple unit tail
        else Nothing



main :: Effect Unit
main = do
  log $ show $ runParser (specificCharParser 'b') "a "

I'd like to implement a "string parser" that parse a specific string. Basically it's converting a String/List of Char to a succession of applicative. Is there a functor tool to do that ?

Vincent L

eg f "abcde" would be converted to f <*> 'a' <*> 'b' ... <*> e

Georgi Lyubenov // googleson78

what you're describing is "just traverse"

Georgi Lyubenov // googleson78

I haven't read your entire post though

Georgi Lyubenov // googleson78

assuming char :: Char -> Parser a

Georgi Lyubenov // googleson78

then traverse char :: [Char] -> Parser [a]

Georgi Lyubenov // googleson78

I'm not sure what you mean by "succession of applicative", but it seems to me like traverse is what you need

Vincent L

but I need to add an instance of traverse ?

Vincent L

It can't be derived automatically from other instance ?

Pedro Minicz

I don't quite understand what you are trying to do, but it seems like you are trying to write parser combinators. If that is correct, I recommend checking this out. It helped me a lot when starting out, also led me to write my own toy parser combinators.

Mini Parser Combinator. GitHub Gist: instantly share code, notes, and snippets.