繁体   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