Skip to content

Instantly share code, notes, and snippets.

@mankyKitty
Last active August 29, 2015 13:59
Show Gist options
  • Save mankyKitty/10569173 to your computer and use it in GitHub Desktop.
Save mankyKitty/10569173 to your computer and use it in GitHub Desktop.
Trying to grok Functor for (a -> m b) type....thingy
-- Working through the Yorgey lectures on Applicatives for Haskell and trying to work out the homework...
-- A parser for a value of type a is a function which takes a String
-- represnting the input to be parsed, and succeeds or fails; if it
-- succeeds, it returns the parsed value along with the remainder of
-- the input.
newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }
-- For example, 'satisfy' takes a predicate on Char, and constructs a
-- parser which succeeds only if it sees a Char that satisfies the
-- predicate (which it then returns). If it encounters a Char that
-- does not satisfy the predicate (or an empty input), it fails.
satisfy :: (Char -> Bool) -> Parser Char
satisfy p = Parser f
where
f [] = Nothing -- fail on the empty input
f (x:xs) -- check if x satisfies the predicate
-- if so, return x along with the remainder
-- of the input (that is, xs)
| p x = Just (x, xs)
| otherwise = Nothing -- otherwise, fail
{-
The task was to implement the Functor for Parser, turns out I'm worse at
this than I had expected and whilst I can knock up a Functor for the basic
types quite quickly. This type required me to be able to map over a function
signature which I had not tried before (a -> m (b,a)) and it proved to be
quite a challenge. But holy shit that was fun. O.O Of course.. that was
question 1... *ahem*
My end result is at the bottom and whilst it type checks at least, I'm still
testing it. But I'm pretty confident since things seem to be placed in the
right locations. :D
-}
[1 of 1] Compiling AParser ( AParser.hs, interpreted )
Ok, modules loaded: AParser.
>
> :i Parser
newtype Parser a
= Parser {runParser :: String -> Maybe (a, String)}
-- Defined at AParser.hs:14:1
instance Functor Parser -- Defined at AParser.hs:63:10
> :t Parser
Parser :: (String -> Maybe (a, String)) -> Parser a
> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
> :t runParser
runParser :: Parser a -> String -> Maybe (a, String)
> :t first
first :: (a -> b) -> (a, c) -> (b, c)
> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
> let x = satisfy isUpper
> :t x
x :: Parser Char
> :t first
first :: (a -> b) -> (a, c) -> (b, c)
> :t (\i -> runParser x i)
(\i -> runParser x i) :: String -> Maybe (Char, String)
> :t (runParser x)
(runParser x) :: String -> Maybe (Char, String)
> :t (runParser x >>= fmap)
<interactive>:1:2:
Couldn't match type ‘Char -> b’ with ‘Maybe (Char, String)’
Expected type: String -> Char -> b
Actual type: String -> Maybe (Char, String)
Possible cause: ‘runParser’ is applied to too many arguments
In the first argument of ‘(>>=)’, namely ‘runParser x’
In the expression: (runParser x >>= fmap)
> :t (runParser x >>=)
(runParser x >>=)
:: (Maybe (Char, String) -> String -> b) -> String -> b
> :t (runParser x)
(runParser x) :: String -> Maybe (Char, String)
> :t (fmap first . runParser x)
<interactive>:1:15:
Couldn't match type ‘(Char, String)’ with ‘a -> b’
Expected type: String -> Maybe (a -> b)
Actual type: String -> Maybe (Char, String)
In the second argument of ‘(.)’, namely ‘runParser x’
In the expression: (fmap first . runParser x)
> :t (first (isUpper) . runParser x)
<interactive>:1:20:
Couldn't match type ‘Maybe (Char, String)’ with ‘(Char, c)’
Expected type: String -> (Char, c)
Actual type: String -> Maybe (Char, String)
In the second argument of ‘(.)’, namely ‘runParser x’
In the expression: (first (isUpper) . runParser x)
> :t (fmap (first (isUpper)) . runParser x)
(fmap (first (isUpper)) . runParser x)
:: String -> Maybe (Bool, String)
first :: (a -> b) -> (a,c) -> (b,c)
first f (a,c) = (f a,c)
instance Functor Parser where
fmap f p = Parser (fmap (first f) . runParser p)
@parsonsmatt
Copy link

I'm working through this right now, and 'watching' your thought process was super helpful. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment