我正在通過Brent Yorgey Haskell course,我無法爲Applicative定義一個好實例。解析器的定義如下:解析器(Haskell)更好的應用實例
newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }
該函數採用一個串,解析一定量的輸入,並返回一個也許元組,其中所述第一值是分析器的類型,和其餘的是未解析的餘數的字符串。例如,這是一個解析器的正整數:
posInt :: Parser Integer
posInt = Parser f
where
f xs
| null ns = Nothing
| otherwise = Just (read ns, rest)
where (ns, rest) = span isDigit xs
該任務是爲解析器創建一個Applicative實例。我們先從一個函子實例(這是比較直接的,我認爲):
first :: (a -> b) -> (a,c) -> (b,c)
first f (a, c) = (f a, c)
instance Functor Parser where
fmap f p = Parser f'
where f' s = fmap (first f) $ (runParser p) s
然後我在試着與應用型:
collapse (Just (Just a)) = Just a
collapse _ = Nothing
extract (Just a, Just b) = Just (a,b)
extract _ = Nothing
appliedFunc :: Parser (a->b) -> Parser a -> String -> Maybe (b, String)
appliedFunc p1 p2 str = extract (f <*> fmap fst result2, fmap snd result2)
where result1 = (runParser p1) str
f = fmap fst result1
result2 = collapse $ fmap (runParser p2) $ fmap snd result1
instance Applicative Parser where
pure a = Parser (\s -> Just (a, s))
p1 <*> p2 = Parser (appliedFunc p1 p2)
...呸。所以我的問題是,我怎樣才能讓我的應用程序實例更清晰,更難讀?我覺得這個問題有一個簡單的答案,但我還沒有能夠把我的頭圍繞在類型上。
@AndrewC對於一個練習,你可能是對的,但是有一個更深的問題與Gabriel Gonzalez的答案有關:'StateT m'不是'Applicative',除非'm'是一個完整的'Monad'。這在變換器之間有所不同:'MaybeT m'也需要一個完整的'Monad','ReaderT m'和'WriterT m'只需要'Applicative',而'ContT m''着名設法得到一個完整的'Monad'並且* no *對'm'的要求。 – 2014-08-31 23:28:37
加布裏埃爾岡薩雷斯的答案總是很好,而且我也已經提高了他的答案。對於monad變換器來說,這個代碼非常簡潔明瞭,這是一個引人注目的廣告。當然,正如你正確指出的那樣,我的評論中的錯誤是加入發生在哪個層次,特別是因爲我之前向另一位提問者解釋了爲什麼monad在解析器中是必需的,因爲他們曾經想要僅在整個過程中使用應用程序!衛生署! – AndrewC 2014-09-01 06:51:38