Using Newtype Package

I am very confused about how to use the newtype package . His documentation seems to suggest that it is very powerful, but I cannot figure out how to use the provided functions (and not the interface) to create some functions that I need. For example, I need functions with signatures:

(Newtype n o) => (o -> o -> o) -> n -> n -> n

(Newtype n o, Functor f) => (o -> f o) -> n -> f n

(Newtype n o, Functor f) => (f o -> o) -> f n -> n

Writing these combinations fmap, packand unpackdoable, but I hope that this is possible and cleaner with mysterious functions alaand ala'(or slight variations, which "raise" function to the new types rather than the "unleashing" of their new types). If that matters, then only those Maybeand I are interested [].

+4
source share
1 answer

Based on the comments above, there seems to be no clean way to write the functions I need using the hofs provided Control.Newtype. However, there seems to be another option: creating instances for non-new types.

Example with the newtype package :

{-# LANGUAGE MultiParamTypeClasses, UndecidableInstances,
             FlexibleInstances #-}

import Control.Newtype

instance (Newtype n o) => Newtype [n] [o] where
  pack = map pack
  unpack = map unpack

instance (Newtype n o) => Newtype (Maybe n) (Maybe o) where
  pack = fmap pack
  unpack = fmap unpack

instance (Newtype n o, Newtype n' o') => Newtype (n -> n') (o -> o') where
  pack f = pack . f . unpack
  unpack f = unpack . f . pack

-- a newtype wrapper for Nums
newtype NNum a = NNum {unNNum :: a}
instance Newtype (NNum a) a where
  pack = NNum
  unpack = unNNum

ntimes5 :: (Num a) => NNum a -> NNum a
ntimes5 = pack sum . replicate 5

foo :: a -> Maybe [a]
foo = undefined

bar :: NNum a -> Maybe [NNum a]
bar = pack foo

As mentioned in bheklilr, this is required UndecidableInstances, but it does not seem to require excessive signatures. However, we can do better using the newtype-generics package :

{-# LANGUAGE TypeFamilies, DeriveGeneric #-}

import Control.Newtype
import GHC.Generics

instance (Newtype a) => Newtype [a] where
  type O [a] = [O a]
  pack = map pack
  unpack = map unpack

instance (Newtype a) => Newtype (Maybe a) where
  type O (Maybe a) = Maybe (O a)
  pack = fmap pack
  unpack = fmap unpack

instance (Newtype a, Newtype b) => Newtype (a -> b) where
  type O (a -> b) = (O a -> O b)
  pack f = pack . f . unpack
  unpack f = unpack . f . pack

newtype NNum a = NNum {unNNum :: a} deriving (Generic)
instance Newtype (NNum a)

ntimes5 :: (Num a) => NNum a -> NNum a
ntimes5 = pack sum . replicate 5

foo :: a -> Maybe [a]
foo = undefined

bar :: NNum a -> Maybe [NNum a]
bar = pack foo

(, Newtype , .) , , - UndecidableInstances FlexibleInstances, . , , , , .

+1

Source: https://habr.com/ru/post/1584971/


All Articles