Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.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
Haskell-在字符串中的指定位置将一个字符更改为另一个指定字符_Haskell - Fatal编程技术网

Haskell-在字符串中的指定位置将一个字符更改为另一个指定字符

Haskell-在字符串中的指定位置将一个字符更改为另一个指定字符,haskell,Haskell,我一直在学习Haskell的一些知识,我想出了一个解决方案,解决了我一直想解决的一个问题 将字符串中指定位置的字符更改为另一个指定字符 changeStr::Int->Char->String->String changeStr x char zs=(取(x-1)zs)++[(changeChar(头(取x zs))char)]++(放x zs) 将一个字符更改为另一个字符 changeChar::Char->Char->Char changeChar x y=y 我只是想问,有没有

我一直在学习Haskell的一些知识,我想出了一个解决方案,解决了我一直想解决的一个问题

  • 将字符串中指定位置的字符更改为另一个指定字符
changeStr::Int->Char->String->String
changeStr x char zs=(取(x-1)zs)++[(changeChar(头(取x zs))char)]++(放x zs)
  • 将一个字符更改为另一个字符
changeChar::Char->Char->Char
changeChar x y=y

我只是想问,有没有其他方法可以用不同的方法以更简单的方式实现这一点?

需要概括的是
changeChar
。它实际上非常接近一个非常常见的Haskell
Prelude
函数,名为
const
。要获得
changeChar
,我们只需要
flip const

const :: a -> b -> a
const a b = a

changeChar :: Char -> Char -> Char
changeChar     = flip const
--             = flip (\a _ -> a)
--             = \_ a -> a
--         _ a = a
除此之外,您的代码相当合理,但可以通过使用函数
splitAt

splitAt :: Int -> [a] -> ([a], [a])
splitAt n xs           =  (take n xs, drop n xs)

changeChar x char xs = 
  let (before, _it:after) = splitAt (x - 1)
  in before ++ (char:after)
这也突出了这个定义的一个小问题,如果索引太大,它将抛出模式匹配失败。我们可以通过使函数返回一个未修改的字符串来修复这个问题,如果我们“从末尾掉下来”

这里还有一个通用模式,即在列表中的特定位置应用修改函数。我们可以这样提取

changeAt :: Int -> (a -> a) -> [a] -> [a]
changeAt n f xs = 
  let (before, after) = splitAt (n-1)
  in case after of
    []       -> []
    (x:rest) -> (f x):rest
我们可以用它来重复这个概念

-- | Replaces an element in a list of lists treated as a matrix.
changeMatrix :: (Int, Int) -> a -> [[a]] -> [[a]]
changeMatrix (i, j) x = changeAt i (changeAt j (const x))

除了函数
changeChar
只是
flip const
,您可以将您的函数重写为

changeStr x char zs = take (x-1) zs ++ [char] ++ drop x zs
如果你想变得复杂,你可以使用
Data.List中的
splitAt
fmap f(a,b)=(a,fb)

如果你想变得非常复杂,你可以问
无点
机器人如何在没有显式函数参数的情况下编写它

changeStr = ((uncurry (++) .) .) . flip ((.) . fmap . (. tail) . (:)) . splitAt . subtract 1

实际上,
constaba=a
,但基本上是一样的。是的,修复了它,但也添加了一点关于
splitAt
。正如@bheklillr所指出的,这个函数和我在这里所做的完全一样:changeChar::Char->Char->Char changeChar x y=y
flip const
。或者更确切地说,
changeChar
flip const
的专门化,其中
a
b
Char
。我原来的回答有一个错误,现在已经更正了。好的,谢谢。但是,如果我有这样一个问题:在[String]中的指定位置将一个字符更改为另一个指定的字符,表示字符串列表,该怎么办?这与在字符串中更改字符的答案类似吗?下面是我为它所做的:--在画布changeRaw::Char->Int->Int->Canvas->Canvas changeRaw Char x y zs=(take(y-1)zs)++[(changeStr x Char(zs!!(y-1)))]++(drop y zs)有没有办法缩短这个?
changeStr idx c str = uncurry (++) $ fmap ((c:) . tail) $ splitAt (idx - 1) str
changeStr = ((uncurry (++) .) .) . flip ((.) . fmap . (. tail) . (:)) . splitAt . subtract 1