0

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?

rampion
  • 82,104
  • 41
  • 185
  • 301
maclunian
  • 7,315
  • 7
  • 32
  • 42
  • 3
    What do you want the new function to do? – interjay May 03 '11 at 22:59
  • @interjay I'd like it to convert a series of list elements e.g: from: [["Off","Off","Off"],["Off,"Off","Off"]] ETA: Basically so I don't need the replaceNth function, I only need the replaceMthNth function to: [["Off","Off","Off"],["Off,"*On*","Off"]] – maclunian May 03 '11 at 23:02
  • 1
    You mean that you want to implement `replaceMthNth` without calling other functions? If so, why would you want to do that? It would just complicate the code. – interjay May 03 '11 at 23:05
  • @interjay it's mainly for a small project and I can't call any other functions - that's the criteria. – maclunian May 03 '11 at 23:19
  • @maclunian: "can't call any other functions" - well, could you use local functions? (like defined using a `where` clause)? Or the y combinator. – rampion May 04 '11 at 00:42
  • 1
    cause I hate to tell you, but `replaceNth m` is a new function. – rampion May 04 '11 at 00:47

5 Answers5

3

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
sigfpe
  • 7,628
  • 2
  • 23
  • 47
2

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.

Don Stewart
  • 134,643
  • 35
  • 355
  • 461
2

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
                      )
                    )
rampion
  • 82,104
  • 41
  • 185
  • 301
1

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)

Rotsor
  • 13,009
  • 5
  • 40
  • 57
0

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]
pat
  • 12,213
  • 1
  • 21
  • 49