Объединить 2 функции списка в 1?

Как бы я объединил следующие 2 функции:

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

в одну функцию?

Является ли это возможным?


person maclunian    schedule 03.05.2011    source источник
comment
Что вы хотите, чтобы новая функция делала?   -  person interjay    schedule 04.05.2011
comment
@interjay Я бы хотел, чтобы он преобразовывал ряд элементов списка, например: from: [[Off,Off,Off],[Off,Off,Off]] ETA: В основном, поэтому мне не нужна функция replaceNth, я только нужна функция replaceMthNth для: [[Off,Off,Off],[Off,On,Off]]   -  person maclunian    schedule 04.05.2011
comment
Вы имеете в виду, что хотите реализовать replaceMthNth без вызова других функций? Если да, то почему вы хотите это сделать? Это только усложнит код.   -  person interjay    schedule 04.05.2011
comment
@interjay это в основном для небольшого проекта, и я не могу назвать другие функции - это критерии.   -  person maclunian    schedule 04.05.2011
comment
@maclunian: нельзя вызывать никакие другие функции - ну, не могли бы вы использовать локальные функции? (как определено с использованием предложения where)? Или комбинатор Y.   -  person rampion    schedule 04.05.2011
comment
потому что я ненавижу говорить вам, но replaceNth m — это новая функция.   -  person rampion    schedule 04.05.2011


Ответы (5)


Это довольно ужасно, но это делает работу:

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
person sigfpe    schedule 04.05.2011

Композиция функций

Функции в Haskell могут быть составлены бесплатно. Например. Имея две функции, f и g, вы можете объединить их в новую функцию: f . g, которая применяет g к аргументу, а затем применяет f к результату. Здесь вы должны уметь использовать композицию таким же образом.

person Don Stewart    schedule 03.05.2011

Хорошо, здесь нет других именованных функций в глобальном пространстве имен или используются какие-либо предложения where или let или любые другие глобальные функции.

{-# 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
                      )
                    )
person rampion    schedule 04.05.2011
comment
Это замечательно! :) Однако вы используете дополнительную функцию fix. - person Rotsor; 04.05.2011
comment
@Rotsor: я тоже использую множество анонимных функций... должны ли мы их учитывать? - person rampion; 04.05.2011
comment
@Rotsor: Хорошо, я удалил fix. (Mu — это конструктор, а не функция). - person rampion; 04.05.2011
comment
Это круто, но следует отметить, что это ужасно продвинутый вопрос для начинающих о композиции функций. - person Don Stewart; 04.05.2011

Я вообще не понимаю, в чем вопрос :), но вот как бы я это реализовал:

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))

Таким образом, вам не нужно проходить список дважды (первый раз с !!, второй раз с replaceNth)

person Rotsor    schedule 04.05.2011

Вот гротескная реализация, которая перестраивает структуру двумерного списка с вложенными списками поверх zip с бесконечными списками:

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]
person pat    schedule 04.05.2011