Question

How would I combine the following 2 functions:

replaceNth n newVal (x:xs)
 | n == 0 = newVal:xs
 | otherwise = x:replaceNth (n-1) newVal xs

replaceMthNth m n v arg = replaceNth m (replaceNth n v (arg !! m)) arg

into a single function?

Is it possible?

Was it helpful?

Solution

This is pretty hideous but it does the job:

replacemn 0 0 z ((x : xs) : xss) = (z : xs) : xss
replacemn 0 n z ((x : xs) : xss) =
  let (ys : yss) = replacemn 0 (n-1) z (xs : xss)
  in ((x : ys) : yss)
replacemn m n z (xs:xss) = xs : replacemn (m-1) n z xss

OTHER TIPS

Function composition

Functions in Haskell may be composed at no cost. E.g. given two functions, f and g, you can compose them into a new function: f . g, which applies g to an argument, then applies f to the result. You should be able to use composition in the same way here.

Ok, here it is with no other named functions in the global namespace, or using any where or let clauses or any other global functions.

{-# LANGUAGE ScopedTypeVariables,RankNTypes #-}
module Temp where
newtype Mu a = Mu (Mu a -> a)

replaceMthNth :: Int -> Int -> a -> [[a]] -> [[a]]
replaceMthNth = (\h (f :: Int -> forall b . b -> [b] -> [b]) -> h f f)
                  ( \replaceNth replaceNth' ->
                    -- definition of replaceMthNth in terms of some replaceNth and replaceNth'
                    \m n v arg -> replaceNth m (replaceNth' n v (arg !! m)) arg
                  )
                  $
                    -- y combinator
                    ((\f -> (\h -> h $ Mu h) $ \x -> f $ (\(Mu g) -> g) x $ x) :: (a -> a) -> a) $
                    (\replaceNth ->
                      -- definition of replaceNth given a recursive definition 
                      (\(n::Int) newVal xs -> case xs of
                          [] -> []
                          (x:xs) -> if n == 0 then newVal:xs else x:replaceNth (n-1) newVal xs
                      )
                    )

I don't understand what the question is at all :), but here is how I would implement it:

modifyNth :: Int -> (a -> a) -> [a] -> [a]
modifyNth n f (x:xs)
  | n == 0 = f x : xs
  | otherwise = x : modifyNth (n-1) f xs

replaceNthMth :: Int -> Int -> a -> [[a]] -> [[a]]
replaceNthMth m n v = modifyNth m (modifyNth n (const v))

This way you don't need to traverse the list twice (first time with !!, second time with replaceNth)

Here's a grotesque implementation that rebuilds the 2d list structure with nested list comprehensions over zips with infinite lists:

replaceMthNth :: Int -> Int -> a -> [[a]] -> [[a]]
replaceMthNth m n v ass = [[if (x,y) == (m,n) then v else a
                            | (y, a) <- zip [0..] as]
                           | (x, as) <- zip [0..] ass]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top