2016-09-04 4 views
1

Я хотел бы сделать эту функцию беспружинной, чтобы ее упростить. Я передаю длину явно вместо того, чтобы вычислять ее, так как мне также нужно это для других функций, и я хотел бы вычислить ее только один раз. Я сумел избавиться от параметра целевой строки, но боролся с двумя другими.Сделать эту функцию tacit

-- Cycle with respect to whitespace (currently only spaces). 
-- Given a source string and its length, and a longer target string 
-- (which may contain spaces) match the source to target such that: 
-- 1. both will have the same length 
-- 2. spaces in the target string will remain spaces 
-- 3. chars from the source string will be cycled 
-- 
-- Example: 
-- src: "ALLY", len: 4 
-- target: "MEET AT DAWN" 
-- Result: "ALLY AL LYAL"     
cycleWS :: String -> Int -> String -> String 
cycleWS str len = fst . (foldr (\x (s, n) -> if x == ' ' then (s ++ " ", n) else (s ++ [str !! (n `mod` len)], n + 1)) ("", 0)) 
+6

Как о том, что проще, разбив его в легкие для понимания деталей, вместо этого? –

+0

Конечно, я открыт для предложений. – dimid

+0

Ну, как насчет функции выстроить строку с пробелами в другой строке, плюс 'цикл'. –

ответ

5

Я серьезно сомневаюсь, что эту конкретную функцию можно сделать более простой, написав ее в бесшумном стиле. Например, вот что я получил от pointfree.io:

cycleWS = ((fst .) .) . flip flip (([]), 0) . (foldr .) . flip flip snd . ((flip . (ap .)) .) . flip flip fst . ((flip . ((.) .) . flip (ap . (ap .) . (. ((,) . (++ " "))) . (.) . if' . (' ' ==))) .) . flip flip (1 +) . ((flip . (liftM2 (,) .) . flip ((.) . (++))) .) . flip flip ([]) . ((flip . ((:) .)) .) . (. flip mod) . (.) . (!!) 
+0

Спасибо за ссылку pointfree.io. – dimid

+9

Кристально-четкие реализации от бессточной, как всегда. – amalloy

+0

Интересно, можно ли исключить флип-флип, так как они отменяются? – dimid

7

По предложению @Reid Бартона:

-- Cycle with respect to whitespace (currently only spaces). 
-- Given a source string and its length, and a longer target string 
-- (which may contain spaces) match the source to target such that: 
-- 1. both will have the same length 
-- 2. spaces in the target string will remain spaces 
-- 3. chars from the source string will be cycled 
-- 
-- Example: 
-- src: "ALLY", len: 4 
-- target: "MEET AT DAWN" 
-- Result: "ALLY AL LYAL"     
cycleWS :: String -> String -> String 
cycleWS = align . cycle 

-- Align with respect to spaces. 
-- Given two strings, source and target, align the source to target such that: 
-- 1. both will have the same length 
-- 2. spaces in the target string will remain spaces 
-- Assume the source string is long enough 
align :: String -> String -> String 
align [] _ = [] 
align _ [] = [] 
align (x:xs) (y:ys) = if isSpace y then y : align (x:xs) ys else x : align xs ys 
+1

Вы можете использовать 'isSpace' для большего количества символов пробела. – dfeuer

+0

Спасибо, отредактирован. – dimid

+2

Кстати, это намного превосходит код, с которого вы начали. У меня аллергия на '!!'. – dfeuer

 Смежные вопросы

  • Нет связанных вопросов^_^