haskell-jp / questions #99 at 2021-10-30 07:43:30 +0900

はじめまして、Haskell初心者で、さらにSlackを使うのも初めてでして、投稿方法など間違っていましたらすみません。
とても簡単な質問かもしれないのですが、
「行列の第 i, j 成分のみ関数 f を適用する」
という関数
matrixsubst :: ( a -> a ) -> [[a]] -> [Int] -> [[a]]
matrixsubst f m [i, j] =
を作りたいのですが、どうしたらよいでしょうか。

具体例としましては、
f = (\x -> x^2),
m=
[[1,2,3]
,[4,5,6]
,[7,8,9]]
i= 2, j=3
とすると、出力として
[[1,2,3]
,[4,5,36]
,[7,8,9]]
を得たい、ということです。
いきなり行列だと難しいので、まずは「リストのi番目のみ関数を適用する関数 modify :: (a -> a) -> Int -> [a] -> [a]」を作ってみると良いと思います。行列の場合はそれを組み合わせればできそうです。
なるほど、ありがとうございます。

modifyを作ってみました。
もっとシンプルな書き方ができるのでしたら教えていただけたら幸いです。

applyvect :: [(a -> b)] -> [a] -> [b]
applyvect [] _ = []
applyvect _ [] = []
applyvect (f:fs) (x:xs) = (f x) : applyvect fs xs

modify :: ( a -> a ) -> [a] -> Int -> [a]
modify f v i = applyvect ((replicate i id) ++ (f : (repeat id))) v

実際、`modify (\x -> x*x) [1,2,3,4,5] 3`
と入力すると、
[1,2,3,16,5]
と出力されます。
関数のリストを作るのではなく、modifyの方でリストにパターンマッチさせつつiを減らしていけばapplyvectを使わなくてもできます。
modify f [] i = [] -- あるいはエラーにする
modify f (x:xs) i | i == 0 = f x : xs
                  | otherwise = x : modify f xs (i - 1)

みたいな感じですね。余談ですが、applyvectは zipWith ($) と等価です。
modifyを2段重ね、つまりmodifyの第1引数としてmodify自身を与えるようにすれば元々のmatrixsubstが実現できると思います。
なるほど、ご丁寧にありがとうがざいました。
勉強になりました!
ちなみに、一般的な質問なのですが、
このような初歩的な質問もこのチャンネルのquestionsに流していいのでしょうか?
もしくはもっと適切な場などがあるのでしょうか?
全然ウェルカムです!
一応そういう質問専用に beginners も作りましたが、どちらでも :ok: です!
みなさま、ありがとうございます、
実は私は作りたいプログラムがあるので、
またbeginnersまたはここで質問させていただきたいと思います。
(今回の件は、ネットで見かけた問題を解いてみようと思ったときにでてきた質問でした。)

またどこかでよろしくおねがいいたします。