在Haskell中识别递归/嵌套类型(类似于类型同义词)

时间:2015-06-22 23:44:16

标签: haskell recursion types type-synonyms

简短问题(已编辑):

是否可以定义函数的类型签名,以便它接受具有任意深度的嵌套类型?我正在寻找类型同义词(NOT newtype)的行为,但识别嵌套/递归类型。

例如,应该可以使用f :: NestedList a -> b[a][[a]]等来调用定义为[[[a]]]的函数。等等。

长问题(原创):

由于不可能在Haskell中使用带有递归类型的类型同义词,是否有针对以下问题的解决方案?

我需要NestedList a这样的同义词,它可以在函数类型定义中标识[a][[a]][[[a]]] ...等等。需要实现的功能的一个例子是:

   flatten :: NestedList a -> [a]

This post使用MultiParamTypeClasses语言扩展显示了flatten的解决方案,但它并没有特别解决我的问题。我需要在类之外定义函数。

修改

flatten只是函数定义的一个例子,我对这个函数不感兴趣。我需要一种机制来使用NestedList a定义一个函数,并使用[[a]][[[a]]]等参数调用它,而不需要额外的类型构造函数,获取方法等。如标题,我需要的东西在嵌套列表上的行为类似于同义词,主要用于为[...[a]...]上的函数提供类型签名,同时确保基类型为a

根据Haskell的强类型系统,这是不可能的,this post揭示了原因。我只是问是否有像机制或变通方法这样的宏/同义词,或者允许我这样做的语言扩展名。

1 个答案:

答案 0 :(得分:6)

你在找这样的东西吗?

data NestedList a = List [NestedList a] | Element a

flatten :: NestedList a -> [a]
flatten (Element x) = [x]
flatten (List xs)   = concatMap flatten xs

修改

正如user2407038建议的那样,如果您有兴趣使用Foldable(包含文件顶部的{-# LANGUAGE DeriveFoldable #-}import Data.Foldable)GHC扩展,那么您可以这样做

data NestedList a = List [NestedList a] | Element a deriving (Foldable)

然后在toList中已经定义了一个名为Foldable的函数,它将从上面生成与flatten相同的输出。

编辑2

这是关于更新问题的其他感兴趣的内容。理想情况下,能够使用

定义Foldable的实例会很好
instance (Foldable t, Functor t, Foldable t') => Foldable (t . t')

其中(t . t') at (t' a)的类型同义词(一种类型级别组合)。这显然不起作用,我倾向于认为有一个合理的解释,为什么引入它会以某种基本方式打破Haskell,但我无法想到它。但是,有一个名为Control.Compose的软件包,它定义了几乎类似的内容(除了事实我们想要一个type同义词而不是newtype)。

newtype (g :. f) a = O { unO :: g (f a) }

这让我们写下以下内容:

toList $ (O) [[1,2,3,4],[4,5,6]]
toList $ (O . O) [[[1],[2,3,4]],[[4],[5,6]]]
toList $ (O . O . O) [[[[1]],[[2,3],[4]]],[[[4]],[[5,6]]]]

这也是有意义的。