For that newtype
is treated as a whole different type in the type system, I'm wondering if there is any way to use pattern matching or iterate a list with newtype, as follow.
newtype Foo = Foo [Int]
bar :: Foo -> Int
bar (x : xs) = x bar xs
bar [] = 0
CodePudding user response:
There are multiple options.
Just manually wrap/unwrap the newtype right in place.
bar (Foo (x : xs)) = x bar (Foo xs) bar (Foo []) = 0
Implement the function on lists, and unwrap it once before passing to the function. In this case the list version is just
sum
, so we can usebar (Foo xs) = sum xs
Make an interface that allows to manipulate
Foo
values as if they were lists.{-# 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
Abstract. You don't really need the particular list deconstructors, you just need some way to implement a fold over the contained data. There is a standard
Foldable
class inbase
for just this, but it would require you container to be parametric over the contained type. Since it's not parametric, you need to useMonoFoldable
class from themono-traversable
package instead.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
Note that generally, this sort of function should be implemented with a strict left fold instead of a right fold.