Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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 创建列表而不是理解列表的替代方法?_Haskell - Fatal编程技术网

Haskell 创建列表而不是理解列表的替代方法?

Haskell 创建列表而不是理解列表的替代方法?,haskell,Haskell,目前,我正在代码中执行类似的操作: --Generate a list of n 'Foo's generateFoos n = [createFoo (show i) | i <- [1..n]] -- Create a Foo with a given name createFoo :: String -> Foo 我在想,除了一直创建范围[1..n],是否还有其他方法可以做到这一点……我更喜欢这种方式: generateFoos n = map (createFoo . s

目前,我正在代码中执行类似的操作:

--Generate a list of n 'Foo's
generateFoos n = [createFoo (show i) | i <- [1..n]]

-- Create a Foo with a given name
createFoo :: String -> Foo
我在想,除了一直创建范围[1..n],是否还有其他方法可以做到这一点……

我更喜欢这种方式:

generateFoos n = map (createFoo . show) [1..n]
还是范围本身就是问题所在?那么我建议:

generateFoos n = map (createFoo . show) (enumFromTo 1 n)
我更喜欢这样:

generateFoos n = map (createFoo . show) [1..n]
还是范围本身就是问题所在?那么我建议:

generateFoos n = map (createFoo . show) (enumFromTo 1 n)

我想说,别担心。创建范围[1..n]在这里并不是一个明显的步骤;这个[1..n]从1到1n,它的构造和其他任何东西一样都是惰性的。这里没有需要消除的隐藏成本。

我想说的是,别担心。创建范围[1..n]在这里并不是一个明显的步骤;这个[1..n]从1到1n,它的构造和其他任何东西一样都是惰性的。这里没有需要消除的隐藏成本。

在我上面的评论中进行扩展-map函数在这里自然出现的原因如下

在Haskell中,列表理解只是do符号的语法糖:

[ 2 * x | x <- [1..10] ]
这是因为列表是单子。使列表成为单子的代码忽略了一些不相关的内容

instance Monad [] where  
    return x = [x]  
    xs >>= f = concat (map f xs)
因此对上面>>=的调用相当于

do { x <- [1..10]; return (2 * x) }
[1..10] >>= \x -> return (2 * x)
concat (map (\x -> return (2 * x)) [1..10])
concat (map (\x -> [2 * x]) [1..10])
如果我们替换对bind的调用,它相当于

do { x <- [1..10]; return (2 * x) }
[1..10] >>= \x -> return (2 * x)
concat (map (\x -> return (2 * x)) [1..10])
concat (map (\x -> [2 * x]) [1..10])
因此,我们将函数\x->[2*x]映射到列表[1..10]上,然后对结果调用concat。但是,由于我们的函数只构建一个元素列表,因此我们可以跳过对concat的调用,并将代码替换为

map (\x -> 2 * x) [1..10]

因此,很自然,相对简单的列表理解可以转化为表达式,涉及在一个范围内映射一个函数。

扩展我上面的评论-映射函数在这里自然出现的原因如下

在Haskell中,列表理解只是do符号的语法糖:

[ 2 * x | x <- [1..10] ]
这是因为列表是单子。使列表成为单子的代码忽略了一些不相关的内容

instance Monad [] where  
    return x = [x]  
    xs >>= f = concat (map f xs)
因此对上面>>=的调用相当于

do { x <- [1..10]; return (2 * x) }
[1..10] >>= \x -> return (2 * x)
concat (map (\x -> return (2 * x)) [1..10])
concat (map (\x -> [2 * x]) [1..10])
如果我们替换对bind的调用,它相当于

do { x <- [1..10]; return (2 * x) }
[1..10] >>= \x -> return (2 * x)
concat (map (\x -> return (2 * x)) [1..10])
concat (map (\x -> [2 * x]) [1..10])
因此,我们将函数\x->[2*x]映射到列表[1..10]上,然后对结果调用concat。但是,由于我们的函数只构建一个元素列表,因此我们可以跳过对concat的调用,并将代码替换为

map (\x -> 2 * x) [1..10]
因此,很自然,相对简单的列表理解可以转化为表达式,涉及在一个范围内映射函数。

无映射,无范围

generateFoos n = unfoldr (doit (createFoo . show)) 1 where 
    doit f acc = if acc > n then Nothing else Just (f acc, acc + 1)
但我不保证本规范的任何特定质量或性质

没有地图,没有范围

generateFoos n = unfoldr (doit (createFoo . show)) 1 where 
    doit f acc = if acc > n then Nothing else Just (f acc, acc + 1)

但我不保证本规范的任何特定质量或性质

@drozzy:很明显。如果你认为map是邪恶的,也许Haskell不是适合你的语言P@NiklasB. 导入数据。Humor@drozzyHaskell列表理解是“do”符号的语法糖分;do表示法是连续一元绑定的语法糖>>=;列表的bind函数只不过是映射列表的元素。这只是让你更接近金属:你的两个版本都完全等同于OP的版本。@n.m.,确实,语法更少sugar@drozzy:这很明显。如果你认为map是邪恶的,也许Haskell不是适合你的语言P@NiklasB. 导入数据。Humor@drozzyHaskell列表理解是“do”符号的语法糖分;do表示法是连续一元绑定的语法糖>>=;列表的bind函数只不过是映射列表的元素。这只是让你更接近金属:你的两个版本都完全等同于OP的版本。@n.m.,的确,用更少的语法,所有列表理解都可以同样自然地转换为映射和过滤的组合。语法糖的意义在于它更甜。我同意——但我认为知道列表理解没有“魔力”是有帮助的。它由解释器/编译器转换成普通的Haskell,您可以自己编写。简单地知道可以将列表理解转换为不同的形式有时可以帮助您编写更可读的代码。类似地,知道有替代do符号的方法可以帮助您将代码中的不纯净部分与纯净部分隔离开来。我只是不同意您关于map在这里更自然的说法。你所有的信息都是可靠的,我同意你的推理。啊,好的。我同意。我将“映射语法是自然的”更改为“映射函数自然产生”所有列表理解都可以转换为映射和过滤器的某种组合。语法糖的意义在于它更甜。我同意——但我认为知道列表理解没有“魔力”是有帮助的。它由解释器/编译器转换成普通的Haskell,您可以自己编写。而且只要知道你可以改变你对清单的理解
转换成不同的形式有时可以帮助您编写更可读的代码。类似地,知道有替代do符号的方法可以帮助您将代码中的不纯净部分与纯净部分隔离开来。我只是不同意您关于map在这里更自然的说法。你所有的信息都是可靠的,我同意你的推理。啊,好的。我同意。我将把“映射语法是自然的”改为“映射函数自然产生”完全没有,只是检查是否有其他方法。完全没有,只是检查是否有其他方法。我喜欢Unfolder。很少使用,但功能强大。我喜欢展开器。很少使用,但功能强大。此外,[1..n]可以参与列表融合,因此列表可能会被完全消除。此外,[1..n]可以参与列表融合,因此列表可能会被完全消除。