是否可以定义函数的类型签名,以便它接受具有任意深度的嵌套类型?我正在寻找类型同义词(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揭示了原因。我只是问是否有像机制或变通方法这样的宏/同义词,或者允许我这样做的语言扩展名。
答案 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
相同的输出。
这是关于更新问题的其他感兴趣的内容。理想情况下,能够使用
定义Foldable
的实例会很好
instance (Foldable t, Functor t, Foldable t') => Foldable (t . t')
其中(t . t') a
是t (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]]]]
这也是有意义的。