我有一个多项式
data Poly a = Poly [a]
Run Code Online (Sandbox Code Playgroud)
我希望能够做类似的事情,fmap (take 3) polynomial但我不能因为我Poly不是真正的函子,因为f我使用的fmap只能是类型[a] -> [b],而不是a -> b.
是否有成语或方式可以表达我想要的东西?
编辑:这是一个功能,它做我想要的
myMap :: ([a] ->[b]) -> P a -> P b
myMap f (P x) = P (f x)
Run Code Online (Sandbox Code Playgroud)
用法:
*Main> myMap (take 3) (P [1..])
P [1,2,3]
Run Code Online (Sandbox Code Playgroud)
你可以从类型sig看到它几乎是 fmap,但并不完全.我显然有能力编写代码myMap,但我只是想知道我是否应该使用另一个成语.
ham*_*mar 10
由于您允许将任何函数应用于系数列表,因此您的数据类型实际上只有两个用途.
Poly [a]是不同的[a].如果您不需要其中任何一个,您也可以使用类型别名.
type Poly a = [a]
Run Code Online (Sandbox Code Playgroud)
现在您可以直接在其上应用任何列表功能.
另一方面,如果您想要一个不同的类型,您可能会发现该newtype包有用.例如,给定此实例.
instance Newtype (Poly a) [a] where
pack = Poly
unpack (Poly x) = x
Run Code Online (Sandbox Code Playgroud)
你现在可以写像
foo :: Poly a -> Poly a
foo = over Poly (take 3)
Run Code Online (Sandbox Code Playgroud)
虽然如果你myMap的目的足够了,这可能是过度的.
除此之外,我认为以这种方式公开数据类型的表示可能不是一个好主意,因为它可以使代码的其余部分紧密依赖于此表示.
这使得以后更改为不同的表示更加困难.例如,您可能希望更改为稀疏表示
data Poly a = Poly [(a, Int)]
Run Code Online (Sandbox Code Playgroud)
这Int是术语的力量所在.我建议考虑你想要公开的操作,并限制自己.例如,拥有一个Functor基于每个元素的实例可能是有意义的.
instance Functor Poly where
fmap f (Poly x) = Poly $ map f x
Run Code Online (Sandbox Code Playgroud)
现在,对稀疏表示的更改使客户端代码保持不变.只有实例(以及依赖于表示的少数其他函数)才必须更改.
instance Functor Poly where
fmap f (Poly x) = Poly $ map (first f) x
Run Code Online (Sandbox Code Playgroud)