Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 哈斯克尔。跟踪索引以生成新列表_List_Haskell_Functional Programming_List Comprehension - Fatal编程技术网

List 哈斯克尔。跟踪索引以生成新列表

List 哈斯克尔。跟踪索引以生成新列表,list,haskell,functional-programming,list-comprehension,List,Haskell,Functional Programming,List Comprehension,我决定学习Haskell,也学习以更实用的方式思考,所以我试图解决非常简单的练习,试图在这个范例中使用一种好的方法 我试图在Haskell中实现这个简单的练习: Input: [2, 4, 1, 1, 2] Output: [True, True, False, False, False, False, True, False, True, True] 因此,输入列表中的元素在 输出列表,奇数元素将为真;每一个 重复次数与输入列表上的值指示的次数相同 如果i ᵗʰ项目是成对的 位置,附加到输出

我决定学习Haskell,也学习以更实用的方式思考,所以我试图解决非常简单的练习,试图在这个范例中使用一种好的方法

我试图在Haskell中实现这个简单的练习:

Input: [2, 4, 1, 1, 2]
Output: [True, True, False, False, False, False, True, False, True, True]
因此,
输入
列表中的元素在
输出
列表,奇数元素将为
;每一个 重复次数与
输入
列表上的值指示的次数相同

如果i ᵗʰ项目是成对的 位置,附加到输出
True
i次到
output
;如果 我 ᵗʰ项目位于奇数位置,追加
False
i次 到
输出
列表

这似乎是一个非常简单的问题,确实如此。但对我来说,没有任何 函数式编程背景,我不知道如何表达 在哈斯克尔

我试图通过使用λ-函数跟踪当前索引 在列表中

    row :: [Integer] -> [Bool]
    row xs = [ (last $ zipWith (\i x -> x) [1..] [0..i]) `mod` 2 == 0
                | j <- xs, i <- [0..j-1] ]
使用最后一种方法似乎可以:

    > let xs = [ 1, 4, 3, 2 ]
    > print $ row xs
    [True,False,False,False,False,True,True,True,False,False]
但问题并没有解决,因为项目不一定是唯一的:

    > let xs = [ 2, 2, 4, 3]
    > print $ row xs
    [True,True,True,True,True,True,True,True,False,False,False]
因为
headfindindices
只给出第一次出现。 (尽管我认为,如果成功的话,这不是一个非常有效的方法 解决这个问题的方法。)


我如何才能以哈斯凯尔式的方式实现我所期待的结果?

以下是我将如何做到这一点

row [] = []
row xs = row' xs 0
   where row' xs i
            | i >= length xs    = []
            | otherwise         = (take (xs !! i) (repeat (isOdd i))) ++ (row' xs (i+1))


isOdd n = n `rem` 2 == 1

但是我没有在这台计算机上安装ghc来测试它。

似乎您已经知道可以使用
zip
将元素与其索引配对。对于每个索引
i
和相应的元素
n
,您希望生成布尔值的
n
副本(使用
replicate
),该布尔值取决于
i
是奇数还是偶数。这意味着
map
将每个元组
(i,n)
ping到布尔值列表,这样就得到了列表列表(
[[Bool]]
)。最后一步是将这些列表与
concat
合并(可以与
map
合并到
concatMap

或者,如果您不喜欢无点样式:

row xs = concatMap (\(i, n) -> replicate n (odd i)) (zip [1..] xs)
另一个解决方案

row :: [Integer] -> [Bool]
row ns = r' True ns
    where
        r' :: Bool -> [Integer] -> [Bool]
        r' b (n:ns) = replicate b n : r' (not b) ns
        r' b   []   = []

(未测试)

如果输入列表中的数字的索引为偶数,则希望将输入列表中的每个元素转换为元素所说的相等
Bool
s的序列,如果索引为奇数,则希望
Bool
True

因此,您不需要索引,而且最好避免索引,这样可以提供更简单、通常更高效的代码。关键是这个值是交替的,它有一个周期性的模式。为了构建这样的周期模式,前奏曲提供了有用的

cycle :: [a] -> [a]

Prelude> take 10 $ cycle [1,2,3]
[1,2,3,1,2,3,1,2,3,1]
Prelude> take 10 $ cycle [True,False]
[True,False,True,False,True,False,True,False,True,False]
整洁,这正是我们需要的

现在,我们可以将输入列表的每个元素与相应的
Bool
配对:

[  2,    2,   4,   3]
[True,False,True,False,...
我们可以使用
zip
生成对,
[(2,True),(2,False),…]
,然后使用一个函数将对转换为适当的
Bool
s序列

但是这种模式非常普遍,我们有一个特殊的高阶函数,
zipWith

因此,如果列表元素的类型是
Int
,我们可以编写

row :: [Int] -> [Bool]
row xs = concat $ zipWith replicate xs (cycle [True,False])
对于类型
整数
,我们不能使用
复制
,但我们可以使用
数据中的
通用副本
。列表
I interepret

遍历输入列表,如果 ᵗʰ项目处于配对位置, 追加到输出真i次到输出;如果我 ᵗʰ项目处于奇数状态 位置,将False i次附加到输出列表

我认为有两种解释。“对于所有元素,如果第i个元素为偶数,则返回真i次。否则,返回假i次”或“对于所有元素,如果i为偶数,则第i个元素包含(v::Int)应返回真v次,如果i为奇数,则返回假v次”。第二个问题已经有了令人满意的答案,因此我将为第一个问题给出一个答案

有些人喜欢参考指数,但在这种情况下,你不需要担心指数。您可以确定有多少个
Bool
s,而无需计算已遍历的元素数

accum f (x:[]) = [x]
accum f (x:xs) = (x):(map f (accum f xs))
此函数接受函数
f
和列表。它将
f
应用于除第一个元素之外的每个元素,然后对列表的尾部进行递归调用,这将再次将
f
应用于剩余的每个元素,以此类推。。。结果是:

accum (+1) [1,1,1,1,1]
[2,3,4,5,6]
功能
+1
应用于第二个元素两次,应用于第二个元素三次,以此类推。 你问这对我们有什么帮助?我们可以这样做:

accum (\x -> [head x] ++ x) $ map (\x -> [x]) [2, 4, 1, 1, 2]
[[2],[4,4],[1,1,1],[1,1,1,1],[2,2,2,2,2]]
我们首先将每个元素转换为一个包含单个项的列表。we
accum
和上面看到的lambda,将头部连接到列表。我们现在可以直接转换为
Bool
s,无需进一步操作

(map . map) odd $ accum (\x -> [head x] ++ x) $ map (\x -> [x]) [2, 4, 1, 1, 2]
[[False],[False,False],[True,True,True],[True,True,True,True],[False,False,False,False,False]]
您想要的是
[Bool]
而不是
[[Bool]]
,所以只需
concat
。请注意,您可以先使用
concat
,然后使用
map
而不是
map。地图

map odd $ concat $ accum (\x -> [head x] ++ x) $ map (\x -> [x]) [2, 4, 1, 1, 2]

我认为您的示例输出应该更改。您在4中缺少了一个false。您没有附加true/false i次,对吗?您将它添加到列表[i]次。似乎工作正常,您只需输入一个
concat
。然而,这是一项不应该用显式累加器递归完成的任务,OP已经走上了一条更好的道路。而且,没有必要定义自己的
isOdd
,因为
odd
已经在前奏中。解释得很好。我想起来容易多了,你的解释给了我如此多的澄清。当然我不想在哈斯克尔。。。然而,或
concat。zipWith(翻转复制)(循环[True,False])
。这几乎是好的。我能看到的唯一问题是
应该被
++
替换。你说得对。我
accum (\x -> [head x] ++ x) $ map (\x -> [x]) [2, 4, 1, 1, 2]
[[2],[4,4],[1,1,1],[1,1,1,1],[2,2,2,2,2]]
(map . map) odd $ accum (\x -> [head x] ++ x) $ map (\x -> [x]) [2, 4, 1, 1, 2]
[[False],[False,False],[True,True,True],[True,True,True,True],[False,False,False,False,False]]
map odd $ concat $ accum (\x -> [head x] ++ x) $ map (\x -> [x]) [2, 4, 1, 1, 2]