如何在Haskell中创建二维数组?

时间:2017-03-28 17:59:36

标签: haskell multidimensional-array functional-programming

我正在尝试通过创建棋盘游戏来学习Haskell。我目前有一个[[Char]]的游戏,我正在尝试创建另一个具有字符“a”的相同列和行的板。我该怎么做呢?您还可以解释如何存储值和访问权限吗?

1 个答案:

答案 0 :(得分:4)

不是创建相同大小但内容不同的新电路板,将此操作视为替换现有电路板的内容可能会有所帮助。当然,因为Haskell是一种不可变的语言,它相同的东西 - 改变某些东西的唯一方法是生成它的新版本 - 但它应该可以帮助你看到这基本上是一个映射操作。

replaceWithA :: [[a]] -> [[Char]]
replaceWithA xss = map (map (const 'a')) xss
-- or, point-free:
replaceWithA = map (map (const 'a'))
-- or, as a list comprehension:
replaceValues xss = [['a' | x <- xs] | xs <- xss]

如果你想深入了解,你可以让编译器为你编写这段代码。 Functor类型类将map概括为不是简单列表的结构:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

这在什么意义上概括map?如果您将f替换为[],则可以看到fmapmap具有相同的签名:

fmap :: (a -> b) -> [a] -> [b]

实际上,这就是[] Functor实例的实施方式:

instance Functor [] where
    fmap = map

无论如何,GHC知道如何单独编写Functor个实例。我将为2D列表定义一个newtype包装,并说出 deriving Functor的神奇单词!

{-# LANGUAGE DeriveFunctor #-}
import Data.Functor

newtype TwoDimensional a = TwoDimensional { getTwoDimensional :: [[a]] } deriving Functor

生成的fmap将具有以下签名:

fmap :: (a -> b) -> TwoDimensional a -> TwoDimensional b

现在,您可以使用标准位机械来替换具有固定值的元素:

replaceWithA :: TwoDimensional a -> TwoDimensional Char
replaceWithA = ('a' <$)

当您获得Haskell及其Functor标准抽象的经验时,您会更好地发现给定操作是更一般模式的实例。仔细设置类型允许您将大量样板委托给编译器,使您能够简洁地声明性地解决问题的有趣部分。