有什么方法可以缩短这些行

时间:2020-09-30 10:41:23

标签: haskell

type Parser a = String -> Maybe (a, String)

parseChar :: Char -> Parser Char
parseChar _ "" = Nothing
parseChar ch (x:xs) | x == ch = Just (ch, xs)
                    | otherwise = Nothing

parseAnyChar :: String -> Parser Char
parseAnyChar "" _ = Nothing
parseAnyChar _ "" = Nothing
parseAnyChar (x:xs) str | isJust res = res
                        | otherwise = parseAnyChar xs str
                        where res = parseChar x str

我是haskell的初学者,我想知道如何以比“递归循环”更多的“ haskell方式”在parseAnyChar中使用parseChar。例如使用地图或其他找不到的东西。

2 个答案:

答案 0 :(得分:2)

是的。一方面,您可以只使用标准函数而不是手动递归来尝试在所有指定的替代方案上使用parseChar

import Data.List (find)

parseAnyChar cs str = case find isJust ress of
    Just res -> res
    Nothing  -> Nothing
 where ress = [parseChar c str | c<-cs]

...或更短

import Data.Maybe (listToMaybe)
import Control.Monad (join)

parseAnyChar cs str = join . listToMaybe $ (`parseChar`str)<$>cs

更有效的解决方案是首先不要尝试所有选项,而要使用Set选项:

import qualified Data.Set as Set

parseOneCharOf :: Set.Set Char -> Parser Char
parseOneCharOf _ "" = Nothing
parseOneCharOf cs (x:xs)
   | x`Set.member`cs  = Just x
   | otherwise        = Nothing

...或更短

import Control.Monad (guard)
parseOneCharOf cs (x:xs) = guard (x`Set.member`cs) >> Just x

答案 1 :(得分:1)

您可以使用Maybe的{​​{3}}实例:

import Control.Applicative((<|>))

parseAnyChar :: Foldable f => f Char -> Parser Char
parseAnyChar xs str = foldr ((<|>) . (`parseChar` str)) Nothing xs

之所以可行,是因为(<|>)的{​​{1}}是Alternative

Maybe

因此,如果左操作数为instance Alternative Maybe where empty = Nothing Nothing <|> r = r l <|> _ = l ,则选择右操作数;如果左操作数为Nothing,则选择第一个操作数。

因此,我们可以将Just …重写为:

parseAnyChar

但是,第二个参数parseAnyChar :: String -> Parser Char parseAnyChar "" _ = Nothing parseAnyChar _ "" = Nothing parseAnyChar (x:xs) str = parseChar x str <|> parseAnyChar xs str 不需要特殊情况,因为""中的逻辑已经覆盖了该参数。因此,我们可以删除第二个子句:

parseChar

现在我们可以将其重写为parseAnyChar :: String -> Parser Char parseAnyChar [] _ = Nothing parseAnyChar (x:xs) str = parseChar x str <|> parseAnyChar xs str 模式。

这也使得可以使用foldr作为字符源。

如果项目数量很大,则可能需要使用更有效的数据结构,例如implemented as [src]