[英]Haskell type unfold then fold to another type
我有這個解析器定義:
newtype Parser a = P { getParser :: String -> Maybe (a, String) }
我也有這個功能:
functionMatching :: Parser (Char, String, Char)
functionMatching = (,,) <$> spot (`elem` "\\") <*> getWord <*> spot (`elem` ".")
我怎樣才能使下面的函數從(Char,String Char)返回中間元素
functionCons:: Parser (Char, String, Char) -> (String, String)
functionCons = undefined
例:
getParser functionMatching "\\x.y"
Just (('\\',"x",'.'),"y")
我想提取x和y。
謝謝!
它將類似於:
functionCons (P p) = P $ fmap (\((_,x,_), s) -> (x,s)) . p
但我建議您聲明Parser a
為函子:
newtype Parser a = P { getParser :: String -> Maybe (a, String) }
deriving (Functor)
functionCons :: Parser (a,b,c) -> Parser b
functionCons = fmap (\(_,x,_) -> x)
當然,這不是完全Parser (a,b,c) -> (b, String)
,但是您需要查看是否確實需要unJust
結果。 例如:
functionCons :: Parser (a,b,c) -> String -> (b,String)
functionCons = unJust . fmap (\(_,x,_) -> x) where
unJust (P p) s = case p s of
Just x -> x
-- if Nothing happens, it will throw a unmatched pattern
正如注釋中正確指出的那樣,類型與請求的類型不同。 沒有functionCons
提供要解析的String
,就不可能獲得准確的簽名Parser (a,b,c) -> (b, String)
。
這里有兩個問題:
我認為您沒有在haskell允許的范圍內使用應用性應用。 functionMatching
返回定界字符,只是稍后將其丟棄。 要放棄解析器匹配,請使用*>
和<*
:
functionMatching''' :: Parser String
functionMatching''' = spot (`elem` "\\") *> getWord <* spot (`elem` ".")
functionCons''' :: String -> (String, String)
functionCons''' = fromJust . getParser functionMatching'''
<*>
, *>
和<*
工作方式很容易記住,它們僅返回>
和<
指向:
f <*> x: fx
x *> y: y
x <* y: x
有一種更慣用的方式來使用解析器。 不要提取Maybe (a,String)
的未解析String
,而是解析它! 那是對getWord
另一個調用。
functionMatching' :: Parser (String, String)
functionMatching' = (,) <$> (spot (=='\\') *> getWord <* spot (=='.')) <*> getWord
functionCons' :: String -> (String, String)
functionCons' = fromJust . evalParser functionMatching'
-- evalParser discards the unparsed String
evalParser :: Parser a -> String -> Maybe a
evalParser p s = fst <$> getParser p s
evalParser
是一個有用的函數,類似於您要導出的runState,evalState和execState 。
解析器的想法是不要過早地離開解析器。 如果沒有匹配項,上面的代碼將遇到錯誤( fromJust
這樣做)。 haskell為此使用Maybe
,並且解析器中已經內置了Maybe
。 我不知道您想使用那個(String,String)
做什么,但是您可能想將其傳遞給函數f :: String -> String -> b
。 然后一個
functionMatching'' :: Parser b
functionMatching'' = f <$> (spot (=='\\') *> getWord <* spot (=='.')) <*> getWord
將更好地處理不匹配問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.