haskell - 如何在 Haskell 中迭代 `newtype` 列表

标签 haskell newtype

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

newtype Foo = Foo [Int]

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

最佳答案

有多种选择。

  1. 只需手动将新类型包装/解开就位。

    bar (Foo (x : xs)) = x + bar (Foo xs)
    bar (Foo []) = 0
    
  2. 在列表上实现该函数,并在传递给函数之前将其解包一次。在本例中,列表版本只是 sum,因此我们可以使用

    bar (Foo xs) = sum xs
    
  3. 创建一个接口(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
    
  4. 摘要。您实际上并不需要特定的列表解构函数,您只需要某种方法来对所包含的数据实现折叠。有一个标准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/

相关文章:

haskell - 在 Haskell 中以树状结构打印二叉搜索树

Haskell 中的函数应用

haskell - 未装箱类型的限制

vector - 如何将迭代器元素的类型强制转换为新类型?

haskell - 如何在 Haskell 中合并不同类型的映射?

haskell - 可分类型类是否有有用的应用程序?

haskell - 如何为具有幻像类型变量的新类型定义 MonadUnliftIO 实例?

haskell - 更广义的新类型推导

haskell - 使用 newtype 包装创建 Ord 实例

haskell - 重写规则不会触发匹配多个实例方法的规则