如何在Haskell中迭代'newtype'列表

b5lpy0ml  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(130)

由于newtype在类型系统中被视为完全不同的类型,我想知道是否有任何方法可以使用模式匹配或使用newtype迭代列表,如下所示。

newtype Foo = Foo [Int]

bar :: Foo -> Int
bar (x : xs) = x + bar xs
bar [] = 0
9w11ddsr

9w11ddsr1#

有多种选择。
1.只需在适当的位置手动 Package /展开新类型。

bar (Foo (x : xs)) = x + bar (Foo xs)
bar (Foo []) = 0

1.在列表上实现函数,并在传递给函数之前将其解包一次。

bar (Foo xs) = sum xs

1.创建一个接口,允许操作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

1.抽象。你并不真的需要特定的列表解构器,你只需要一些方法来实现对所包含数据的 fold。在base中有一个标准的Foldable类,但它要求你的容器对所包含的类型是参数化的。由于它不是参数化的,你需要使用mono-traversable包中的MonoFoldable类来代替。

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

请注意,一般来说,这种函数应该使用 * 严格左折叠 * 而不是右折叠来实现。

相关问题