首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Newtype包

使用Newtype包
EN

Stack Overflow用户
提问于 2015-04-28 03:18:51
回答 1查看 355关注 0票数 4

我对如何使用newtype包感到非常困惑。它的文档似乎暗示这是非常强大的,但我不知道如何使用提供的函数(而不是接口)来创建一些我需要的函数。例如,我想要一个带有签名的函数:

代码语言:javascript
复制
(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

使用fmappackunpack的组合编写这些函数是可行的,但我希望使用神秘的alaala'函数(或者稍微变化一下,将函数“提升”到新类型而不是从新类型中“分离”出来)可以更清晰地实现。如果重要的话,我特别感兴趣的函数器是Maybe[]

EN

回答 1

Stack Overflow用户

发布于 2015-04-28 23:30:40

根据上面的评论,似乎没有一种干净的方法来使用Control.Newtype提供的hof来编写我需要的函数。然而,似乎还有另一种选择:为非新类型创建实例。

newtype包的一个示例:

代码语言:javascript
复制
{-# 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

正如bheklilr提到的,这需要UndecidableInstances,但它似乎不需要过多的签名。但是,我们可以使用newtype-generics包做得更好:

代码语言:javascript
复制
{-# 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实例,这样可以节省扩展和一次导入。)因此,由于UndecidableInstancesFlexibleInstances而出现的任何问题现在都是没有意义的。总结了herehere类型族与fundeps的比较。这个例子似乎是一个类型族提供了明显的胜利的案例。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29904170

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档