Last active
August 29, 2015 13:59
-
-
Save mankyKitty/10569173 to your computer and use it in GitHub Desktop.
Trying to grok Functor for (a -> m b) type....thingy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- 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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm working through this right now, and 'watching' your thought process was super helpful. Thanks!