由于 newtype
在类型系统中被视为完全不同的类型,我想知道是否有任何方法可以使用模式匹配或使用 newtype 迭代列表,如下所示。
newtype Foo = Foo [Int]
bar :: Foo -> Int
bar (x : xs) = x + bar xs
bar [] = 0
最佳答案
有多种选择。
只需手动将新类型包装/解开就位。
bar (Foo (x : xs)) = x + bar (Foo xs) bar (Foo []) = 0
在列表上实现该函数,并在传递给函数之前将其解包一次。在本例中,列表版本只是
sum
,因此我们可以使用bar (Foo xs) = sum xs
创建一个接口(interface),允许像列表一样操作
Foo
值。{-# LANGUAGE PatternSynonyms #-} {-# COMPLETE (:%), FooNil #-} pattern (:%) :: Int -> Foo -> Foo pattern x :% xs <- Foo (x : (Foo -> xs)) where x :% xs = Foo (x : getFoo xs) pattern FooNil :: Foo pattern FooNil = Foo [] bar :: Foo -> Int bar (x :% xs) = x + bar xs bar FooNil = 0
摘要。您实际上并不需要特定的列表解构函数,您只需要某种方法来对所包含的数据实现折叠。有一个标准
Foldable
base
中的 class 就是为了实现这一点,但这需要容器对所包含的类型进行参数化。由于它不是参数化的,因此您需要使用MonoFoldable
来自mono-traversable
包的类。import Data.MonoTraversable type instance Element Foo = Int import MonoFoldable Foo where ofoldr f (Foo (x:xs)) e = f x $ ofoldr f (Foo xs) e ofoldr _ (Foo []) e = e bar = ofoldr (+) 0
请注意,一般来说,此类功能应该使用严格的左折叠而不是右折叠来实现。
关于haskell - 如何在 Haskell 中迭代 `newtype` 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74041945/