Haskell:定义图像的滚动功能

时间:2016-04-07 14:32:40

标签: haskell functional-programming

我是Haskell的新手,正在处理代表type Img = [String]的图像。 我想创建一个向上或向下移动图像1行或更多行的函数。

下面的图片示例。

img 1= [ "XX XX"          
       , "  X  "
       , "XX XX"
       ]      

我的目标是编写一个函数moveImg :: Int -> Img -> Img,将图像垂直翻译,包裹; e.g:

 moveImg 1 (img 1) = -- Move up by 1
   [ "  X  "
   , "XX XX"  
   , "XX XX"          
   ]

 moveImg (-1) (img 1) =  -- Move down by 1
   [ "XX XX"  
   , "XX XX"     
   , "  X  "
   ]

2 个答案:

答案 0 :(得分:2)

你朋友的代码不起作用,因为它缺少模运算符 - 所以旋转不是“包裹”。 Carsten的代码是有效的(他的代码通过将列表与自身堆叠起来然后采用适当的切片来工作;它将“包裹”,因为它是堆叠的);这是另一种选择。这只是the array rotation problem

    import Data.List (splitAt)
    import Data.Tuple (swap)



    rotate :: Int -> [a] -> [a]

    rotate k xs = uncurry (++) $ swap $ splitAt (k `mod` length xs) xs 

我们将列表拆分为两半 - 我们mod为了启用旋转,swap为后面的前端,并将它们添加到一起。 swap适用于元组(splitAt返回)。 uncurry只强制列表连接(++)来处理元组而不是两个单独的参数。它将类型a -> b -> c的函数转换为(a, b) -> c类型。

以下是一些测试 - forM_就像for循环一样用于按顺序打印每一行。

    import Control.Monad (forM_)
    main = do
      let img = ["XX XX",          
                 "  X  ",
                 "XX XX"]      
      putStrLn "Up is positive"
      forM_ (rotate 1 img) print
      putStrLn "Down is negative"
      forM_ (rotate (-1) img) print

提供以下输出:

    Up is positive
    "  X  "
    "XX XX"
    "XX XX"
    Down is negative
    "XX XX"
    "XX XX"
    "  X  "

如果您愿意,可以创建Up / Down数据类型,而不是使用正/负值。 e.g。

    data Direction = Up | Down
    rotate :: Direction -> Int -> [String] -> [String]
    rotate d k xs = . . . 

答案 1 :(得分:1)

或许可以采用更基本的方法

moveImg n xs = take len $ drop (mod n len) $ cycle xs
        where len = length xs