递归函数

时间:2011-03-30 10:35:02

标签: haskell recursion

我在练习时遇到问题,我应该定义一个函数,该函数将整数,字符和字符串作为输入,并返回将字符放入字符串中由整数指定的位置的结果,例如,将3'a'"haskell"提供给该函数应该会产生"hasakell"

putinto :: Int -> Char -> String -> String
putinto

4 个答案:

答案 0 :(得分:6)

以这种方式思考:有一个列表,其中第一个元素称为'x',列表的其余部分称为'xs'(在Haskell中,这将被写为(x:xs)),你要么将您给定的值前置到该位置列表为0.否则,您将自行调用列表的剩余部分(并减少该值)。

putinto :: Int -> a -> [a] -> [a]
putinto 0 value list   = value : list
putinto n value (x:xs) = x : putinto (n-1) value xs

如果它看起来很奇怪,(x:xs)实际上是一个“解构”列表。 x表示列表的第一个元素,xs('s'表示'复数',因此它是'x'的复数')是列表的其余部分。

所以用零调用它实际上会预先给定给定的值,如

putinto 0 'a' "haskell"  -- yields 'ahaskell'

用两个调用它将是:

putinto 2 'a' "haskell"
-- same as 'h' : putinto 1 'a' "askell"
-- same as 'h' : 'a' : putinto 0 'a' "skell"
-- same as 'h' : 'a' : 'a' : "skell"
-- same as "haaskell"

你仍然需要关心错误检查(如果给定的位置是负数,或者大于列表长度怎么办?)。

答案 1 :(得分:3)

int j = 3;
char a = 'a';
string x = "haskell";

string part1 = x.Substring(0, j);
string part2 = x.Substring(j);
string result = part1 + a + part2;

这将在C#

中发挥作用

答案 2 :(得分:3)

在针对涉及Haskell中的列表的问题编写显式递归解决方案之前,值得检查是否可以使用PreludeData.List中的列表函数完成相同的任务。在这种情况下,splitAt可以提供帮助:

splitAt 3 "haskell"
("has","kell")

因此,您可以通过拆分,删除和追加来轻松解决问题:

putInto :: Int -> Char -> String -> String
putInto n c xs = let (ys,zs) = splitAt n xs in ys ++ (c:zs)

为了好玩,以上也可以使用(-> r)的应用实例以无点样式编写:

putInto :: Int -> Char -> String -> String
putInto n c = ((++) . fst <*> (c:) . snd) . splitAt n

答案 3 :(得分:0)

我认为这应该很容易阅读。我列举了解释的行:

1. putInto :: Int -> Char -> String -> String
2. putInto 0 a xs     = a:xs
3. putInto _ a []     = [a]
4. putInto n a (x:xs) = x : putInto (n-1) a xs

这里发生了什么?第一行是类型签名。第二行检查您是否希望在前面设置字符(即索引0)。

第三行和第四行用于我们希望在第0个索引之后插入它的时间。第三行检查我们要插入的列表是否为空,在这种情况下,我们只返回仅包含a的列表。

在第四行中,我们知道字符串的第一个索引仍然是第一个,因此我们只是在尾部递归,在此过程中根据需要减少n