当我注意到Elm不支持列表推导时,我试图在Elm中模拟魔方。在Haskell甚至是Python中,我会写一些类似的东西:
ghci> [2*c | c <- [1,2,3,4]]
[2,4,6,8]
我在榆树找不到路。我必须写的实际列表理解是(在Haskell中):
ghci> let x = [0,1,3,2]
ghci> let y = [2,3,1,0]
ghci> [y !! fromIntegral c | c <- x]
[2,3,0,1]
其中fromIntegral :: (Integral a, Num b) => a -> b
将Integer
变为Num
。
在Elm中,我尝试使用Arrays:
x = Array.fromList [0,1,3,2]
y = Array.fromList [2,3,1,0]
Array.get (Array.get 2 x) y
我开始遇到Maybe
类型的问题:
Expected Type: Maybe number
Actual Type: Int
事实上,我不得不抬头看看它们是什么。我没有在可能的情况下工作,而是用列表做了一些事情:
x = [0,1,3,2]
y = [2,3,1,0]
f n = head ( drop n x)
map f y
我不知道这是否有效或正确,但它在我尝试的情况下有效。
我想我的两个主要问题是:
map
)maybe
类型?head ( drop n x)
来获取列表的第n个元素是否有效?答案 0 :(得分:5)
Elm并不支持列表推导:https://github.com/elm-lang/Elm/issues/147
Evan所说的风格指南说“喜欢地图,过滤和折叠”,所以..使用`map:
map ((y !!).fromIntegral) x
或
map (\i-> y !! fromIntegral i) x
评论者指出(!!)不是有效的Elm(它是有效的Haskell)。我们可以将其定义为:
(!!) a n = head (drop n a)
,一个完整的功能。
或者也许是
(!!) a n = case (head (drop n a)) of
Just x -> x
Nothing -> crash "(!!) index error"
答案 1 :(得分:3)
我对榆树知之甚少,所以我无法回答它是否支持列表推导(无论是哪种方式都无法通过Google找到任何内容),但我可以回答你的其他两个问题。
如何绕过Array示例中的Maybe类型?
Array.get
的类型为Int -> Array a -> Maybe a
,这意味着它返回Nothing
或Just x
,其中x
是给定索引处的值。如果你想将其中一个操作的结果提供给另一个操作,那么在Haskell中你可以做到
Array.get 2 x >>= \i -> Array.get i y
或者用符号表示:
do
i <- Array.get 2 x
Array.get i y
但是,通过快速搜索,似乎Elm可能支持或不支持所有monadic类型,但希望您仍然可以使用case语句来解决这个问题(这不是很有趣)
case Array.get 2 x of
Nothing -> Nothing
Just i -> Array.get i y
事实上,我建议您编写一个函数来为您执行此操作,它只是在Haskell中直接克隆>>=
Maybe
:
mayBind :: Maybe a -> (a -> Maybe b) -> Maybe b
mayBind Nothing _ = Nothing
mayBind (Just x) f = f x
然后你可以用它作为
Array.get 2 x `mayBind` (\i -> Array.get i y)
调用
head (drop n x)
来获取列表的第n个元素是否有效?
不,但两者都不是直接索引,相当于head . drop n
。对于列表,索引始终为O(n)
复杂度,这意味着从列表中获取n
元素需要n
个步骤。数组具有不同的结构,这使得它们以对数时间进行索引,这显着更快。对于小列表(&lt; 100元素),这并不重要,但是一旦你开始获得超过一百或一千个元素,它就开始成为瓶颈。列表非常适合简单的代码,不必是最快的,因为它们通常更方便。现在,我不知道这在Elm中是如何被翻译的,可能是Elm会将它们转换为Javascript数组,这些数组是真正的数组并且可以在O(1)
时间内转换为索引。如果Elm在编译后使用自己版本的Haskell列表,那么你仍然会有一个减速。