我编写了一个Const3
与 非常相似的Const
新类型,但包含三个给定类型参数中的第一个:
newtype Const3 a b c = Const3 { getConst3 :: a }
我可以为这种新类型定义很多有用的实例,但我必须自己完成。
但是,我在类型级别应用的函数类似于函数
\a b c -> a
这@pl
告诉我相当于const . const
.
两者(.)
和const
都有匹配的新类型包装器:Compose
和Const
. 所以我想我可以写:
type Const3 = Compose Const Const
并自动继承有用的实例,例如:
instance Functor (Const m)
instance (Functor f, Functor g) => Functor (Compose f g)
-- a free Functor instance for Const3!
但 GHC 不同意:
const3.hs:5:23:
Expecting one more argument to ‘Const’
The first argument of ‘Compose’ should have kind ‘* -> *’,
but ‘Const’ has kind ‘* -> * -> *’
In the type ‘Compose Const Const’
In the type declaration for ‘Const3’
这似乎与和的种类Compose
有关Const
:
*Main> :k Compose
Compose :: (* -> *) -> (* -> *) -> * -> *
*Main> :k Const
Const :: * -> * -> *
因此,经过一番搜索,我发现有一个名为 GHC 的扩展PolyKinds
程序允许我执行以下操作:
{-# LANGUAGE PolyKinds #-}
newtype Compose f g a = Compose { getCompose :: f (g a) }
newtype Const a b = Const { getConst :: a }
好像魔法一样,这些种类是正确的:
*Main> :k Compose
Compose :: (k -> *) -> (k1 -> k) -> k1 -> *
*Main> :k Const
Const :: * -> k -> *
但我仍然无法将它们组合起来写Const3 = Compose Const Const
。
const3.hs:12:23:
Expecting one more argument to ‘Const’
The first argument of ‘Compose’ should have kind ‘* -> *’,
but ‘Const’ has kind ‘* -> k0 -> *’
In the type ‘Compose Const Const’
In the type declaration for ‘Const3’
是什么赋予了?有没有一些聪明的方法可以做到这一点,所以我可以从和继承Functor
等实例中获益?Const
Compose
(作为旁注,导致我的最初想法
Const3
是写:newtype Const3 a b c = Const3 { getConst3 :: a } instance Monoid m => Category (Const3 m) where id = Const3 mempty Const3 x . Const3 y = Const3 (mappend x y)
捕捉到幺半群是单对象类别的想法。如果有一个解决方案仍然允许我以某种方式编写上述实例,那就太好了。)