Idris中的字符串替换功能

时间:2018-07-25 23:39:44

标签: string replace idris

在Idris中,字符串是基元,而不是Haskell中的列表。因此,我希望会有某种基本的replace : (needle : String) -> (replacement : String) -> (haystack : String) -> String函数la Data.Text.replace。我找不到这个。但是我想,也许我可以在Data.List.Utils.replace中找到一些replace : Eq a => (needle : List a) -> (replacement : List a) -> (haystack : List a) -> List a函数,因为Idris确实提供了unpack : String -> List Charpack : Foldable t => t Char -> String。但是,我也找不到Idris中定义的列表的replace。我已经在文档和GitHub repo中搜索了几样东西,并在REPL中用:browse进行了查找,但是都算不上运气。当然,良好的旧Idris的replace函数用于处理类型,而不是用于字符串……(这使我很高兴,但不能解决我的问题)。

最后,我将Data.List.Utils.replace从Haskell移植了过来,但是我不知道它的性能,更糟糕的是,它还不是全部。而且,对于我通常认为是原始操作的代码,它需要大量的代码(假设字符串是原始数据)。

spanList : (List a -> Bool) -> List a -> (List a, List a)
spanList _ [] = ([],[])
spanList func list@(x::xs) =
  if func list
  then
    let (ys,zs) = spanList func xs
    in (x::ys,zs)
  else ([],list)

breakList : (List a -> Bool) -> List a -> (List a, List a)
breakList func = spanList (not . func)

partial
split : Eq a => List a -> List a -> List (List a)
split _ [] = []
split delim str =
  let (firstline, remainder) = breakList (isPrefixOf delim) str in
  firstline :: case remainder of
                    [] => []
                    x => if x == delim
                         then [] :: []
                         else split delim (drop (length delim) x)

partial
strReplace : String -> String -> String -> String
strReplace needle replacement =
  pack . intercalate (unpack replacement) . split (unpack needle) . unpack

我将重塑它,直到获得全部,因为我看不出为什么不能将其全部确定,但是与此同时,我还缺少什么?人们真的在Idris中进行了很少的字符串操作以至于根本无法使用它吗?我假设contrib中至少会有一些东西。您如何在Idris中进行字符串替换?

1 个答案:

答案 0 :(得分:2)

对于以后找到这个并想要实现的任何人,这是我目前拥有的:

module ListExt

%default total
%access public export

splitOnL' : Eq a => (delim : List a)    -> {auto dprf : NonEmpty delim   }
                 -> (matching : List a) -> {auto mprf : NonEmpty matching}
                 -> List a -> (List a, List (List a))
splitOnL' _ _ [] = ([], [])
splitOnL' delim m@(_::m') list@(x::xs) =
  if isPrefixOf m list
  then
    case m' of
      [] => ([], uncurry (::) $ splitOnL' delim delim xs)
      (m_ :: ms) => splitOnL' delim (m_ :: ms) xs
  else
    let (l, ls) = splitOnL' delim delim xs in
    (x :: l, ls)

splitOnL : Eq a => (delim : List a) -> {auto dprf : NonEmpty delim}
                -> List a -> List (List a)
splitOnL delim [] = []
splitOnL delim list@(_::_) = uncurry (::) $ splitOnL' delim delim list

substitute : Eq a => List a -> List a -> List a -> List a
substitute [] replacement = id
substitute (n :: ns) replacement = intercalate replacement . splitOnL (n :: ns)

strReplace : String -> String -> String -> String
strReplace needle replacement = pack . substitute (unpack needle) (unpack replacement) . unpack

我可能会尝试将PR提交回去,以将其包含在Idris的基础库中。 警告:我没有进行过性能测试,甚至没有严格测试过;我已经在大约十几个案例上运行了它,这似乎是正确的。如果仅分析算法,就会发现它效率不如您期望的那样。到目前为止,我还没有成功实现更高效的版本,同时又保持了总体水平。