我的职能如下:
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]的东西。当函数为supposed以选择不在列表中的图片时,我希望它可以编写"X"。为此,我将使用函数text "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"发布于 2018-12-08 17:19:05
您不能就这样丢弃不加载的图片;如果尝试加载3张图片并以[some_pic, some_other_pic]结束,您如何知道哪个图片没有加载?您需要一个类型为[Maybe Picture]的列表,其中Just pic表示成功加载的图片,Nothing表示失败。那么您的函数看起来就像
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 (这是一个很好的建议)
import Control.Monad
blockToPicture :: Int -> [Maybe Picture] -> Maybe Picture
blockToPicture n pics = join (lookup n (zip [0..] pics))由于lookup :: a -> [(a,b)] -> Maybe b和b在这里是Maybe Picture,所以我们有这样一个场景:如果n太大,lookup返回Nothing;如果所需的图片无法加载,则返回Just Nothing;如果找到所需的图片,则返回Just (Just pic)。来自Control.Monad的Control.Monad函数减少了lookup返回给我们想要的“常规”Maybe Picture的Maybe (Maybe Picture)值。
发布于 2018-12-08 15:17:12
blocoParaPicture ::Int -> Picture -> Picture blocoParaPicture b l b==0 = if elem pic1 l,然后pic1 blocoParaPicture文本"X“pic1 b==1 = if elem pic2 l然后pic2 blocoParaPicture文本"X”\x= if elem pic3 l然后pic3 blocoParaPicture text "X“ 我得到错误的“变量不在范围”的图片。
表达式elem x xs检查给定的x是否在list xs中。在编写pic1时,代码中没有这样的变量,在任何地方都没有定义。在任何情况下,您都不想在列表中搜索特定的值,而是想知道给定的位置是否“存在”,也就是说,列表是否足够长。
此外,您不能只在函数中使用这种类型“写”。在Haskell中,输入和输出反映在类型上。这是一个纯函数,它接受一些参数并计算结果,没有副作用。
因此,您可以在这里返回一个Maybe Picture,它的值是Nothing还是Just pic,这取决于您是否可以返回图片。也可以使用Either String Picture,其中值的形式为Left string或Right pic。让我们选择后一种选择。
blocoParaPicture :: Int -> [Picture] -> Either String Picture在实现方面,我们可能会偏离主题来讨论错误管理(因为问题是访问某个位置可能会失败)。但在这一点上,我认为最好避免这种迂回,所以让它保持(相对)简单。
直接递归(最简单)
最简单的最直接的方法是直接递归(如@chepner在下面的注释中所建议的)。
blocoParaPicture :: Int -> [Picture] -> Either String Picture
blocoParaPicture _ []     = Left "X"
blocoParaPicture 0 (x:_)  = Right x
blocoParaPicture n (x:xs) = safe (n-1) xs!! 确保继承
如果您确实想使用标准访问函数!!,一种方法是构造一个“安全”无限列表(但在一般情况下可能效率低下)。
import Data.List 
blocoParaPicture :: Int -> [Picture] -> Either String Picture
blocoParaPicture n xs = zs !! n 
                        where zs = [Right x | x <- xs] ++ repeat (Left "X")list zs是由两个列表组成的无限列表。第一个[Right x | x <- xs],它与原始列表一样,但是每个元素x都变成了Right x。然后,从那时起,所有元素都以Left "X"形式表示失败。一般而言,上述方法可能效率低下。如果您在列表中寻找一个大的n:
[Right 1, Right 2] ++ [Left "X", Left "X", ...您正在执行许多不必要的步骤,因为您可以在第一个列表结束时停止。但对于小型n来说,效果很好。
使用lookup的
还有一种类似于您尝试使用elem函数的可能性,就是在索引上使用lookup。通过设计,本功能安全可靠。
lookup :: Eq a => a -> [(a, b)] -> Maybe b按照这种方法,首先构造列表,
[(0,x0), (1,x1), (2,x2) ...(k,xk)]然后查找给定的n来返回关联的xn (或Nothing)。
blocoParaPicture' :: Int -> [Picture] -> Maybe Picture
blocoParaPicture' n xs = lookup n (zip [1..] xs)但是,当找不到时,这会返回Nothing。但是如果您愿意,可以通过Either通过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))当您只需要一个简单的访问函数时,这肯定有点复杂。但在事情不那么简单的情况下却很方便。
https://stackoverflow.com/questions/53683452
复制相似问题