簡體   English   中英

Haskell類型展開,然后折疊為另一種類型

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM