简体   繁体   中英

Haskell - Attempting Monad instance - syntax issues

I have the following definitions:

newtype Parser a = Parser { parse :: String -> [(a,String)] }


instance Functor Parser where
 fmap g (Parser pa) = Parser { parse = \s -> [(g a,s') | (a,s') <- pa s] }


instance Applicative Parser where
 pure x = Parser { parse = \s -> [(x,s)] }
 (<*>) (Parser pg) (Parser pa) = Parser { parse = \s -> [(g a,s'') | (g,s') <- pg s, (a, s'') <- pa s'] }



instance Monad Parser where
 return = pure
 (>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | [(a, s')] <- (pa s), [(b,s'')] <- (g a) s'] } 

The trouble is with the bind operator implementation. I am not sure why I get type error there. I am attempting to define the bind operator on the same lines as (<*>)

The error is:

parser.hs:17:58: error:
    • Couldn't match expected type ‘(a, String)’
                  with actual type ‘[(a, t0)]’
    • In the pattern: [(a, s')]
      In a stmt of a list comprehension: [(a, s')] <- (pa s)
      In the expression:
        [(b, s'') | [(a, s')] <- (pa s), [(b, s'')] <- (g a) s']
    • Relevant bindings include
        g :: a -> Parser b (bound at parser.hs:17:20)
        pa :: String -> [(a, String)] (bound at parser.hs:17:16)
        (>>=) :: Parser a -> (a -> Parser b) -> Parser b
          (bound at parser.hs:17:2)
   |
17 |  (>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | [(a, s')] <- (pa s), [(b,s'')] <- (g a) s'] }
   |                                                          ^^^^^^^^^

parser.hs:17:92: error:
    • Couldn't match expected type ‘t0 -> [[(b, String)]]’
                  with actual type ‘Parser b’
    • The function ‘g’ is applied to two arguments,
      but its type ‘a -> Parser b’ has only one
      In the expression: (g a) s'
      In a stmt of a list comprehension: [(b, s'')] <- (g a) s'
    • Relevant bindings include
        s' :: t0 (bound at parser.hs:17:63)
        g :: a -> Parser b (bound at parser.hs:17:20)
        (>>=) :: Parser a -> (a -> Parser b) -> Parser b
          (bound at parser.hs:17:2)
   |
17 |  (>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | [(a, s')] <- (pa s), [(b,s'')] <- (g a) s'] }

Update: For the sake of completeness, based on the answers. Here is what worked:

instance Monad Parser where
 return = pure
 (>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | (a, s') <- (pa s), (b,s'') <- parse (g a) s'] } 

A guard pattern like [(a, s')] <- (pa s) means you're expecting pa s to return a list of lists with each exactly one pair of a and s in them, whereas it actually returns just a list with any number of those pairs in them.

Basically, drop the brackets (and also from the other binding) and then it should work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM