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。例如使用地图或其他任何东西,但我找不到。
解决方案
是的。一方面,您可以只使用标准函数而不是手动递归来尝试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
推荐阅读
- esb - MQ 和 ESB 的区别
- java - 在 HTML 文件中为 Tomcat 中的 .war 文件引用 servlet
- c# - C#:如何使用 varbinary(Max) 将图像上传到 SQL Server 数据库
- react-native - 为什么使用 Apollo 进行客户端查询会导致网络错误?
- java - 双重验证
- gnome-terminal - 如何从源代码构建 gnome-terminal?
- chart.js - 将 Chart.js 与 TypeScript 一起使用时如何使用 legendCallback 或类似方法
- database - Oracle 数据库外键约束
- angular - 使用角度数据源使用 API 中的数据填充材料表
- wordpress - Wordpress 仪表板未完全加载