Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.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_Gloss_Juicy Pixels - Fatal编程技术网

Haskell 从列表中选择特定图片

Haskell 从列表中选择特定图片,haskell,gloss,juicy-pixels,Haskell,Gloss,Juicy Pixels,我有以下功能: blockToPicture :: Int -> [Picture] -> Picture blockToPicture n [pic1,pic2,pic3] | n==0 = ... | n==1 = ... | otherwise = ... 如果n==0我想选择pic1,如果n==1我想选择pic2。否则我想选择pic3。问题

我有以下功能:

blockToPicture :: Int -> [Picture] -> Picture
blockToPicture n [pic1,pic2,pic3] | n==0 = ...
                                  | n==1 = ...
                                  | otherwise = ...
如果
n==0
我想选择
pic1
,如果
n==1
我想选择
pic2
。否则我想选择
pic3
。问题是其中一张图片没有加载,因此它不会出现在列表中。 我用类似于
[pic1,pic2,pic3]
的东西代替了
[pic1,pic3]
。 当函数设置为
以选择列表中不存在的图片时,我希望它改为写
“X”
。为此,我将使用函数
改为文本“X”
。问题是我不知道如何让它编写
“X”
,而不是选择错误的图片

编辑: 我创建了以下函数,但由于某些原因,我在图片中得到了错误“变量不在范围内”

blocoParaPicture :: Int -> [Picture] -> Picture
blocoParaPicture b l | b==0 = if elem pic1 l then pic1 else text "X"
                     | b==1 = if elem pic2 l then pic2 else text "X"
                     | otherwise = if elem pic3 l then pic3 else text "X"
我将错误“变量不在范围内”添加到图片中

blocoParaPicture :: Int -> [Picture] -> Picture
blocoParaPicture b l | b==0 = if elem pic1 l then pic1 else text "X"
                     | b==1 = if elem pic2 l then pic2 else text "X"
                     | otherwise = if elem pic3 l then pic3 else text "X"
表达式
elem x xs
检查给定的
x
是否在列表
xs
中。在编写
pic1
的代码中,范围中没有这样的变量,它没有在任何地方定义。在任何情况下,您都不想在列表中搜索特定的值,而是想知道给定的位置是否“存在”,即列表是否足够长

此外,您不能仅在具有这种类型的函数中“写入”。在Haskell中,输入和输出反映在类型上。这是一个纯函数,它接受一些参数并计算结果,没有副作用

因此,您可以在这里返回一个
可能是Picture
,它的值为
Nothing
Just pic
,具体取决于您是否可以返回图片。或者您可以使用
字符串图片
,其中值的形式为
左字符串
右图片
。让我们选择后者

blocoParaPicture :: Int -> [Picture] -> Either String Picture
在实施方面,我们可能会偏离主题,进入错误管理的讨论(因为问题是,访问某个职位可能会失败)。但在这一点上,我认为最好避免绕道,所以让我们保持(相对)简单

直接递归(最简单)

最简单最直接的方法是直接递归(正如@chepner在下面的评论中所建议的)

确保
成功

如果您确实想使用标准访问功能
,其中一种方法(但在一般情况下可能效率低下)是构造一个“安全”的无限列表

import Data.List 

blocoParaPicture :: Int -> [Picture] -> Either String Picture
blocoParaPicture n xs = zs !! n 
                        where zs = [Right x | x <- xs] ++ repeat (Left "X")
您正在执行许多不必要的步骤,因为第一个列表结束时您可能会停止。但对于较小的
n
来说效果很好

使用
查找

还有一种可能性,类似于您尝试使用
elem
函数,就是在索引上使用
lookup
。此功能在设计上是安全的

lookup :: Eq a => a -> [(a, b)] -> Maybe b
按照这种方法,首先构建列表

[(0,x0), (1,x1), (2,x2) ...(k,xk)]
然后查找给定的
n
,返回相关的
xn
(或

但如果未找到,则返回
Nothing
。但是如果您愿意,您可以通过
maybe::b->(a->b)->maybe a->b转换到

blocoParaPicture :: Int -> [Picture] -> Either String Picture
blocoParaPicture n xs = maybe (Left "X") Right (lookup n (zip [1..] xs))

当您只需要一个简单的访问函数时,这当然有点太复杂了。但是,在事情不那么简单的情况下,这是很方便的。

你不能仅仅丢弃一张没有加载的图片;如果您尝试加载3张图片,结果是
[一些图片,一些其他图片]
,您如何知道哪一张没有加载?您需要一个类型为
[可能图片]
的列表,其中
仅pic
表示成功加载的图片,
表示失败。那么你的函数看起来像

blockToPicture :: Int -> [Maybe Picture] -> Maybe Picture
blockToPicture _ []          = Nothing                  -- No pictures to choose from
blockToPicture 0 (Nothing:_) = Nothing                  -- Desired picture failed to load
blockToPicutre 0 (x:_)       = x                        -- Found desired picture!
blockToPicture n (_:xs)      = blockToPicture (n-1) xs  -- This isn't it; try the next one
调整豪尔赫·阿德里亚诺的建议,使用
查找
(这是一个很好的方法)

由于
lookup::a->[(a,b)]->可能是b
b
这里是
可能是图片
,我们有
如果
n
太大,
lookup
返回
Nothing
<如果所需图片未能加载,则代码>仅为Nothing
;如果找到所需图片,则代码>仅为(仅为pic)
。来自
控件的
join
函数。Monad
可能(可能图片)
值减少到
lookup
返回到我们想要的“常规”
可能图片

在这里您可以再次在
[pic1,pic2]
[pic1]
[]
等列表上进行模式匹配,每次更换不再覆盖的箱子。但是我建议您实现一个递归模式,在该模式中,您在递减的索引上递归,并在列表的尾部递归。不,不,不,您应该使用类型为
[可能是图片]
的列表。文本“X”函数做什么?可以使用(字符串图片)代替。在病理情况下,
n
length xs
大得多,只检查
n>length xs
比在无限列表的足够大的范围内迭代更有效。或者直接编写递归,而不是使用
bPP[]=左“X”;bpp0(x:u)=右x;bppn(x:xs)=bppn(n-1)xs
。事实上,你是对的,我考虑过了。在任何情况下,他都是一个初学者,应该只看一个只有3个元素的列表。。。每种方法都会教他一些东西。你的建议补充道,也许这是最好的。试图坚持
可能会使它变得不必要的复杂。我还找到了
的“安全”替代方案
之前,但只找到了
Data.List.Safe
,但它使用了与标准函数相同的名称,这在这里会令人困惑。
blocoParaPicture' :: Int -> [Picture] -> Maybe Picture
blocoParaPicture' n xs = lookup n (zip [1..] xs)
blocoParaPicture :: Int -> [Picture] -> Either String Picture
blocoParaPicture n xs = maybe (Left "X") Right (lookup n (zip [1..] xs))
blockToPicture :: Int -> [Maybe Picture] -> Maybe Picture
blockToPicture _ []          = Nothing                  -- No pictures to choose from
blockToPicture 0 (Nothing:_) = Nothing                  -- Desired picture failed to load
blockToPicutre 0 (x:_)       = x                        -- Found desired picture!
blockToPicture n (_:xs)      = blockToPicture (n-1) xs  -- This isn't it; try the next one
import Control.Monad

blockToPicture :: Int -> [Maybe Picture] -> Maybe Picture
blockToPicture n pics = join (lookup n (zip [0..] pics))