Idris 中的字符串替换函数
String replace function in Idris
在 Idris 中,字符串是基本类型,而不是像 Haskell 中那样的列表。因此,我希望有某种原始的 replace : (needle : String) -> (replacement : String) -> (haystack : String) -> String
函数如 la Data.Text.replace
. I have not been able to find this. But I thought, perhaps I will be able to find some replace : Eq a => (needle : List a) -> (replacement : List a) -> (haystack : List a) -> List a
function a la Data.List.Utils.replace
, since Idris does provide unpack : String -> List Char
and pack : Foldable t => t Char -> String
. However, I have not been able to find replace
for Lists defined in Idris, either. I have searched the documentation and the GitHub repo 用于一些事情,并在 REPL 中使用 :browse
进行探索,但都没有运气。当然,老 Idris 的 replace
函数适用于处理类型,而不是字符串...(这在某种程度上让我很高兴,但并没有解决我的问题)。
最后,我从 Haskell 移植了 Data.List.Utils.replace
,但我想知道它的性能,更糟糕的是,它并不完整。此外,对于我通常认为的原始操作(假设字符串是原始操作),它需要大量代码。
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 中进行字符串替换?
对于后来发现此问题并想要实施的任何人,这是我目前所拥有的:
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 的基础库中。 警告:我没有对此进行过性能测试,甚至根本没有对其进行过严格测试;我有 运行 大约十几个案例,它似乎是正确的。如果你只是分析算法,你会发现它并不像你希望的那样高效。到目前为止,我还没有成功地在保持整体性的同时实现更高效的版本。
在 Idris 中,字符串是基本类型,而不是像 Haskell 中那样的列表。因此,我希望有某种原始的 replace : (needle : String) -> (replacement : String) -> (haystack : String) -> String
函数如 la Data.Text.replace
. I have not been able to find this. But I thought, perhaps I will be able to find some replace : Eq a => (needle : List a) -> (replacement : List a) -> (haystack : List a) -> List a
function a la Data.List.Utils.replace
, since Idris does provide unpack : String -> List Char
and pack : Foldable t => t Char -> String
. However, I have not been able to find replace
for Lists defined in Idris, either. I have searched the documentation and the GitHub repo 用于一些事情,并在 REPL 中使用 :browse
进行探索,但都没有运气。当然,老 Idris 的 replace
函数适用于处理类型,而不是字符串...(这在某种程度上让我很高兴,但并没有解决我的问题)。
最后,我从 Haskell 移植了 Data.List.Utils.replace
,但我想知道它的性能,更糟糕的是,它并不完整。此外,对于我通常认为的原始操作(假设字符串是原始操作),它需要大量代码。
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 中进行字符串替换?
对于后来发现此问题并想要实施的任何人,这是我目前所拥有的:
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 的基础库中。 警告:我没有对此进行过性能测试,甚至根本没有对其进行过严格测试;我有 运行 大约十几个案例,它似乎是正确的。如果你只是分析算法,你会发现它并不像你希望的那样高效。到目前为止,我还没有成功地在保持整体性的同时实现更高效的版本。