Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.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
Haskell 创建映射操作,使每个输入元素生成1个或多个输出元素?_Haskell - Fatal编程技术网

Haskell 创建映射操作,使每个输入元素生成1个或多个输出元素?

Haskell 创建映射操作,使每个输入元素生成1个或多个输出元素?,haskell,Haskell,最近,我试图找出如何在Haskell中进行一些编程 我想做一些简单的操作。现在,我遇到了一个类似于本例的操作: input = [1,2,3,4] output = [1,2,2,3,3,3,4,4,4,4] 也就是说,对于input中的每个元素x,在output中生成x元素。因此,对于输入中的元素1,将[1]附加到输出中。然后,对于输入中的元素2,将元素[2,2]附加到输出。然后,对于元素3,添加[3,3,3]等。该算法应仅适用于标准数字 我知道这很容易,在“普通”命令式编程中执行它也很简单

最近,我试图找出如何在Haskell中进行一些编程

我想做一些简单的操作。现在,我遇到了一个类似于本例的操作:

input = [1,2,3,4]
output = [1,2,2,3,3,3,4,4,4,4]
也就是说,对于
input
中的每个元素
x
,在
output
中生成
x
元素。因此,对于输入中的元素
1
,将
[1]
附加到输出中。然后,对于输入中的元素
2
,将元素
[2,2]
附加到输出。然后,对于元素
3
,添加
[3,3,3]
等。该算法应仅适用于标准数字

我知道这很容易,在“普通”命令式编程中执行它也很简单,但由于Haskell的函数是无状态的,我在如何处理这一点上遇到了问题


有谁能给我一些提示,一个绝对的哈斯克尔初学者如何应对这个问题?

你刚刚发现了单子

以下是您所做工作的总体思路:

对于输入中的每个
a
-元素(即容器类型
ma
,此处
[a]
),您可以指定一个完整的新容器
mb
。但最终的结果是,您只需要一个“扁平”容器
mb

>让我们看一下<代码> Monad < /Cord>类类的定义:

class (Applicative m) => Monad m where
  return :: a -> m a
  (>>=) :: m a -> (a -> m b) -> m b
这正是你需要的。和列表是Monad的一个实例,因此您可以编写

replicates :: [Int] -> [Int]
replicates l = l >>= \n -> replicate n n
或者,这可以写下来

replicates l = do
   n <- l
   replicate n n
复制l=do
n=\\->返回n

。。。或者至少在GHC的一些旧版本中,我认为它现在使用了更优化的列表理解实现。您仍然可以使用
-XMonadComprehensions
标志启用该脱糖变体。

作为初学者,我更容易理解以下内容:

concat$map(\x->take x$repeat x)[1,2,3,4]


对于“列表为单子”,重要的是要知道在引擎盖下也有“concat”操作(在绑定定义中),IMO是另一个解决方案,利用列表理解:

output = [ n | n <- input , m <- [1..n] ]
一个简单的解决方案:

rep (x:xs) = replicate x x ++ rep xs
rep [] = []
提示:

  • replicate 5“a”
    给出了
    [“a”、“a”、“a”、“a”]
    ,它对第二个参数中的任何类型都起相同的作用,但第一个参数必须是Int类型
  • 运算符
    ++
    连接两个列表
  • 因此,
    rep
    的推断类型是
    [Int]->[Int]
    ,如果需要使用其他类型,则应使用转换函数

take x$repeat x
只是
replicate x
concat$map…
通常写为
concatMap…
,或者使用列表单子表示法,
[1..4]>=(\x->replicate x)
(后者有很好的“处理器”感觉,但YMMV)。pointfree的狂热者可能会将最后一个写为。
output = [ n | n <- input , m <- [1..n] ]
for n in input:            -- n <- input
   for m in range(1,n+1):  -- m <- [1..n]    (in Python the second extreme is excluded, hence +1)
      print n              -- the n in [ n | ... ]
output = [ n | n <- input , _ <- [1..n] ]
rep (x:xs) = replicate x x ++ rep xs
rep [] = []