我是否可以将这种新类型实现为其他类型的组合?
  我写了一个与Const类似的新类型Const3 ,但包含三个给定类型参数中的第一个: 
newtype Const3 a b c = Const3 { getConst3 :: a }
我可以为这种新类型定义很多有用的实例,但我必须自己完成。
但是,我在类型级别上应用的函数类似于函数
a b c -> a
  @pl告诉我等价于const . const  const . const 。 
  (.)和const都有匹配的newtype包装: 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 :: * -> * -> *
  所以经过一番搜索之后,我发现有一个称为PolyKinds的GHC扩展,它允许我执行如下操作: 
{-# 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’
  是什么赋予了?  有没有一些聪明的方法来做到这一点,所以我可以从Const和Compose获得继承Functor等实例的好处? 
  (作为一个侧面说明,导致我进入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)
捕捉幺半群是单个对象类别的想法。 如果有一个解决方案仍然允许我以某种方式编写上述实例,那将会很好。)
  令人困惑的事情 - 或者至少让我困惑的事情 - 就是*表现为具体类型,而不是类型变量。  因此,如果没有PolyKinds , Compose的类型更像是: 
compose :: (A -> A) -> (A -> A) -> A -> A
  至关重要的是,我们不能用A -> A代替A ,因为它们会是不同的类型,所以,通过相同的逻辑,我们不能用* -> *代替* 。 
  即使与PolyKinds ,种类仍然不正确。  特别是, Compose期望(k -> *)作为它的第一个参数,并且您正试图给它(k -> (k2 -> *)) 。 
  你被迫返回*种类的原因是因为你使用的是newtypes ,newtypes必须返回一个具体的类型(即kind * )。  我试图通过将Compose变成一个类型同义词来克服这个问题,它最终具有我们想要的类型(与PolyKinds ): 
type Compose f g a = (f (g a))
λ> :k Compose
Compose :: (k1 -> k) -> (k2 -> k1) -> k2 -> k
  然而,使用这仍然给了我一个类似的错误,我不确定我们是否能够正常工作。  问题出现了,因为将Compose应用到第一个Const给了我们一个带有*的类型,可能是因为限制了类型别名,例如: 
λ> :k Compose Const
Compose Const :: (k -> *) -> k -> k1 -> *
  从其他答案看来,它似乎并不那么容易,但是如果你想要的唯一的东西是“免费”的实例,一个快速的方法是在GeneralizedNewtypeDeriving扩展中对常规Const使用newtype : 
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE PatternSynonyms #-}
module ConstThree (Const3,pattern Const3,getConst3) where
import Data.Foldable
import Data.Traversable
import Control.Applicative
import Data.Monoid
newtype Const3 a b c = MkConst3 (Const a c) deriving (Functor,Applicative,Foldable,Traversable,Eq,Ord,Show,Monoid)
pattern Const3 :: a -> Const3 a b c
pattern Const3 x = MkConst3 (Const x)
getConst3 :: Const3 a b c -> a
getConst3 (Const3 x) = x
  在上面,我也使用PatternSynonyms来隐藏客户端对Const的内部使用。 
这就是你得到的:
λ> :t Const3
Const3 :: a -> Const3 a b c
λ> :t getConst3
getConst3 :: Const3 a b c -> a
λ> :i Const3
pattern Const3 :: a -> Const3 a b c
        -- Defined at /tmp/alpha-dbcdf.hs:13:5
type role Const3 representational phantom phantom
newtype Const3 a b c = MkConst3 (Const a c)
        -- Defined at /tmp/alpha-dbcdf.hs:10:5
instance Eq a => Eq (Const3 a b c)
  -- Defined at /tmp/alpha-dbcdf.hs:10:100
instance Functor (Const3 a b)
  -- Defined at /tmp/alpha-dbcdf.hs:10:59
instance Ord a => Ord (Const3 a b c)
  -- Defined at /tmp/alpha-dbcdf.hs:10:103
instance Show a => Show (Const3 a b c)
  -- Defined at /tmp/alpha-dbcdf.hs:10:107
instance Monoid a => Applicative (Const3 a b)
  -- Defined at /tmp/alpha-dbcdf.hs:10:67
instance Foldable (Const3 a b)
  -- Defined at /tmp/alpha-dbcdf.hs:10:79
instance Traversable (Const3 a b)
  -- Defined at /tmp/alpha-dbcdf.hs:10:88
instance Monoid a => Monoid (Const3 a b c)
  -- Defined at /tmp/alpha-dbcdf.hs:10:112
正如所料,您可以做到:
instance Monoid m => Category (Const3 m) where
  id = Const3 mempty
  Const3 x . Const3 y = Const3 (mappend x y)
                        链接地址: http://www.djcxy.com/p/43459.html
                        上一篇: Can I implement this newtype as a composition of other types?
