Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 替换Haskell中字符串数组中的第n个字符_List_Haskell_Functional Programming - Fatal编程技术网

List 替换Haskell中字符串数组中的第n个字符

List 替换Haskell中字符串数组中的第n个字符,list,haskell,functional-programming,List,Haskell,Functional Programming,我是Haskell和函数式编程的新手。我正在尝试实现一个函数来获取这样的列表 ["abc", "def", "ghi"] 例如,希望能够替换yth元素中的第x个字符 replaceChar 1 2 'd' arr 会产生 ["abc", "ded", "ghi"] 所以本质上第一个参数是元素,第二个是字符串的位置,第三个是字符,最后一个是[string] 此函数的签名如下所示: replaceChar :: Int -> Int -> Char -> [String] -

我是Haskell和函数式编程的新手。我正在尝试实现一个函数来获取这样的列表

["abc", "def", "ghi"]
例如,希望能够替换yth元素中的第x个字符

replaceChar 1 2 'd' arr
会产生

["abc", "ded", "ghi"]
所以本质上第一个参数是元素,第二个是字符串的位置,第三个是字符,最后一个是[string]

此函数的签名如下所示:

replaceChar :: Int -> Int -> Char -> [String] -> [String]
任何帮助都将不胜感激。谢谢

试试这个:

replace n 0 c (x:xs) = (replace' n c x) : xs
replace n m c (x:xs) = x : (replace n (m-1) c xs)
  where
    replace' 0 c (x:xs) = c : xs
    replace' n c (x:xs) = x : (replace' (n-1) c xs)
在这里,您只需遍历列表,直到相应的索引为
0
,然后替换匹配列表中的字符。我们使用相同的原则替换列表中的字符。我们遍历它,当我们到达指定的索引时,我们用新的字符替换该索引处的字符

最后,所有的东西都会互相消耗,以替换旧的结构,这次是替换字符。

试试这个:

replace n 0 c (x:xs) = (replace' n c x) : xs
replace n m c (x:xs) = x : (replace n (m-1) c xs)
  where
    replace' 0 c (x:xs) = c : xs
    replace' n c (x:xs) = x : (replace' (n-1) c xs)
在这里,您只需遍历列表,直到相应的索引为
0
,然后替换匹配列表中的字符。我们使用相同的原则替换列表中的字符。我们遍历它,当我们到达指定的索引时,我们用新的字符替换该索引处的字符


最后,所有内容都会相互替换,以替换旧结构,这次是替换字符。

让我们将此问题分解为两个函数,一个用于用新字符替换字符串中的元素,另一个用于替换字符串列表

我想推荐如下:

replaceCharInStr :: Int -> Char -> String -> String
replaceCharInStr 0 c (s:ss) = c:ss
replaceCharInStr n c (s:ss) = s : ???
replaceCharInStr n c [] = error "replaceCharInStr: Empty string"
这里我们说,如果
n
为0,用
c
忽略字符串的第一个元素,然后如果
n
不是0并且列表至少有一个元素,则在某个元素前面加上该元素(练习留给读者。提示:递归),然后如果字符串为空,则引发错误。我要说的是,我并不特别喜欢这里使用的
error
,最好返回
字符串,或者我们可以说
replaceCharInStr n c[]=[c]
。我们还可以将类型签名更改为
replaceCharInStr::Int->a->[a]->[a]
,因为这不是字符串特有的

对于下一个函数,我们要做的是获取一个索引,并在该索引处应用一个函数。通常,此函数的类型为

applyAt :: Int -> (a -> a) -> [a] -> [a]
并且可以使用类似于
replaceCharInStr

applyAt :: Int -> (a -> a) -> [a] -> [a]
applyAt 0 f (x:xs) = f x : xs
applyAt n c (x:xs) = x : ???
applyAt n c [] = error "applyAt: Empty list"
事实上,这与
replaceCharInStr
的形状完全相同,因此如果您实现了这一形状,那么您应该能够按照
applyAt
实现
replaceCharInStr

replaceCharInStr n c xs = applyAt n (\x -> c) xs
-- Or                   = applyAt n (const c) xs
然后您的
replaceChar
函数可以实现为

replaceChar :: Int -> Int -> Char -> [String] -> [String]
replaceChar n m c strings = applyAt n (replaceCharInStr m c) strings
-- Or                     = applyAt n (applyAt m (const c)) strings

剩下的就是实现
applyAt

让我们将这个问题分解为两个函数,一个用新字符替换字符串中的元素,另一个用于字符串列表

我想推荐如下:

replaceCharInStr :: Int -> Char -> String -> String
replaceCharInStr 0 c (s:ss) = c:ss
replaceCharInStr n c (s:ss) = s : ???
replaceCharInStr n c [] = error "replaceCharInStr: Empty string"
这里我们说,如果
n
为0,用
c
忽略字符串的第一个元素,然后如果
n
不是0并且列表至少有一个元素,则在某个元素前面加上该元素(练习留给读者。提示:递归),然后如果字符串为空,则引发错误。我要说的是,我并不特别喜欢这里使用的
error
,最好返回
字符串,或者我们可以说
replaceCharInStr n c[]=[c]
。我们还可以将类型签名更改为
replaceCharInStr::Int->a->[a]->[a]
,因为这不是字符串特有的

对于下一个函数,我们要做的是获取一个索引,并在该索引处应用一个函数。通常,此函数的类型为

applyAt :: Int -> (a -> a) -> [a] -> [a]
并且可以使用类似于
replaceCharInStr

applyAt :: Int -> (a -> a) -> [a] -> [a]
applyAt 0 f (x:xs) = f x : xs
applyAt n c (x:xs) = x : ???
applyAt n c [] = error "applyAt: Empty list"
事实上,这与
replaceCharInStr
的形状完全相同,因此如果您实现了这一形状,那么您应该能够按照
applyAt
实现
replaceCharInStr

replaceCharInStr n c xs = applyAt n (\x -> c) xs
-- Or                   = applyAt n (const c) xs
然后您的
replaceChar
函数可以实现为

replaceChar :: Int -> Int -> Char -> [String] -> [String]
replaceChar n m c strings = applyAt n (replaceCharInStr m c) strings
-- Or                     = applyAt n (applyAt m (const c)) strings

剩下的就是实现
applyAt

首先需要注意:虽然您的签名非常好,但实际上您并没有使用处理字符串的事实,它也可以是任何其他类型的列表。在签名中使用完全通用的类型变量(小写字母)而不是
Char
,通常是一个很好的方法:

replaceAtXY :: Int -> Int -> a -> [[a]] -> [[a]]
接下来,请注意,问题基本上可以归结为修改普通(非嵌套)列表的第n个元素。在外部列表中,修改第y个子列表,即在该子列表中修改第x个元素

那么“修改”在Haskell中是什么意思呢?我们不能改变课程2的元素。我们需要一个函数,它接受一个列表并返回另一个列表,并基于一个对列表中的单个元素进行操作的函数来执行此操作

modifyNth :: Int -> (a->a) -> [a]->[a]
注意,这有点类似于标准函数
map::(a->b)->[a]->[b]

一旦拥有了该功能,就可以轻松实现

modifyXY :: Int -> Int -> (a->a) -> [[a]]->[[a]]
modifyXY x y f nList = modifyNth y (modifyNth x f) nList
(顺便说一句,
nList
参数不需要编写,您可以修改它)


1关于这是一个好主意的原因:显然,它允许您在更一般的设置中使用该功能。但更重要的是,它为类型检查器提供了额外的信息,您不会对包含的元素本身做任何事情。这实际上有助于捕获更复杂应用程序中的许多错误


2实际上,即使语义很好,你也可以在圣单子中使用。

首先需要注意的是:虽然你的签名很好,但你实际上没有使用处理字符串的事实,它也可以是任何其他类型的列表。这对我来说通常是个好主意