种类与 GHC.Generics 不匹配
Kind mismatch with GHC.Generics
我正在尝试在 Haskell 中编写通用向量 space 实现。我的实现如下:
import qualified GHC.Generics as G
import GHC.Generics hiding (V1)
class GVecSpace v where
addVs :: v -> v -> v
scaleV :: Double -> v -> v
instance GVecSpace (G.V1 a) where
addVs _ _ = undefined
scaleV _ _ = undefined
instance GVecSpace (G.U1 a) where
addVs _ x = x -- no value
scaleV _ x = x -- no value
instance (GVecSpace (f a), GVecSpace (g a)) => GVecSpace ((f :+: g) a) where
addVs (L1 x) (L1 y) = L1 $ addVs x y
addVs (R1 x) (R1 y) = R1 $ addVs x y
scaleV d (L1 x) = L1 $ scaleV d x
scaleV d (R1 x) = R1 $ scaleV d x
instance (GVecSpace (f a), GVecSpace (g a)) => GVecSpace ((f :*: g) a) where
addVs (x1 :*: x2) (y1 :*: y2) =
addVs x1 y1 :*: addVs x2 y2
scaleV d (x1 :*: x2) =
scaleV d x1 :*: scaleV d x2
instance (GVecSpace c) => GVecSpace (K1 i c p) where
addVs (K1 x) (K1 y) = K1 $ addVs x y
scaleV d (K1 x) = K1 $ scaleV d x
instance (GVecSpace (f p)) => GVecSpace (M1 i c f p) where
addVs (M1 x) (M1 y) = M1 $ addVs x y
scaleV d (M1 x) = M1 $ scaleV d x
instance (Generic a, GVecSpace (Rep a)) => GVecSpace a where
addVs x y =
G.to $ addVs (G.from x) (G.from y)
scaleV d x =
G.to $ scaleV d (G.from x)
但是 GHC 抱怨是因为 Rep a
有错误的种类:
Expecting one more argument to ‘Rep a’
The first argument of ‘GVecSpace’ should have kind ‘*’,
but ‘Rep a’ has kind ‘* -> *’
In the instance declaration for ‘GVecSpace a’
我应该更改什么才能使其正常工作?一种选择是使 GVecSpace
仅适用于 * -> *
的种类,但这看起来很尴尬。有没有办法避免这种情况?
要创建一个使用 GHC.Generics
的库,我们首先需要一些先决条件。
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
import GHC.Generics as G
泛型的所有表示都带有一个名为 "the parameter" p
的额外类型参数。您可以在 Generic a
class、type Rep a :: * -> *
中的类型 Rep a
中看到这一点。数据类型的表示不仅仅是另一种数据类型,它是一种类型 * -> *
,与 Functor
s 和 Monad
s 相同。它以另一种类型作为参数。大多数时候,根据通用表示定义 class 的实例,我们将忽略参数。
由于额外的参数,定义一个非通用的 class 很有用。我们稍后会添加更多内容。
class VecSpace v where
addVs :: v -> v -> v
scaleV :: Double -> v -> v
...
class、GVecSpace
的通用版本有一个关于所有值类型的额外参数 a
。我们之前在所有地方使用 v
,我们将使用 f a
。我们将通过在 VecSpace
的名称前加上 g
来为 GVecSpace
创建新名称。
class GVecSpace f where
gaddVs :: f a -> f a -> f a
gscaleV :: Double -> f a -> f a
GVecSpace
class 有点笨拙,只适用于 * -> *
类型,但它仅用于制作 VecSpace
的默认实现。您将在其他任何地方使用 VecSpace
。
只有一个构造函数的单元类型是向量 space。请注意,G.U1
未应用于参数。
instance GVecSpace G.U1 where
gaddVs _ x = x -- no value
gscaleV _ x = x -- no value
两个向量space的乘积是一个向量space。请注意,f
和 g
以及 f :*: g
不适用于参数类型。
instance (GVecSpace f, GVecSpace g) => GVecSpace (f :*: g) where
gaddVs (x1 :*: x2) (y1 :*: y2) =
gaddVs x1 y1 :*: gaddVs x2 y2
gscaleV d (x1 :*: x2) =
gscaleV d x1 :*: gscaleV d x2
对于K1
,我们从类型中删除最后一个参数p
,并根据非泛型VecSpace
来定义它。 c
参数只有kind*
,是普通类型,不可能是GVecSpace
.
的实例
instance (VecSpace c) => GVecSpace (K1 i c) where
gaddVs (K1 x) (K1 y) = K1 $ addVs x y
gscaleV d (K1 x) = K1 $ scaleV d x
对于 M1
元数据节点,我们从类型中删除最终参数 p
。
instance (GVecSpace f) => GVecSpace (M1 i c f) where
gaddVs (M1 x) (M1 y) = M1 $ gaddVs x y
gscaleV d (M1 x) = M1 $ gscaleV d x
现在我们可以 return 到 VecSpace
class 并填写当它的表示有 GVecSpace
时如何成为 VecSpace
的默认值实例。我们将参数转换为表示 from
类型 v
,对表示执行操作的泛型版本,然后在我们“大功告成。
class VecSpace v where
addVs :: v -> v -> v
scaleV :: Double -> v -> v
default addVs :: (Generic v, GVecSpace (Rep v)) => v -> v -> v
addVs x y = to (gaddVs (from x) (from y))
default scaleV :: (Generic v, GVecSpace (Rep v)) => Double -> v -> v
scaleV s = to . gscaleV s . from
使用
假设您已经观察到 Double
s 形成一个向量 space
instance VecSpace Double where
addVs = (+)
scaleV = (*)
我们可以根据 VecSpace
.
中的 default
派生元组的工作 VecSpace
实例
instance (VecSpace a, VecSpace b) => VecSpace (a, b)
我正在尝试在 Haskell 中编写通用向量 space 实现。我的实现如下:
import qualified GHC.Generics as G
import GHC.Generics hiding (V1)
class GVecSpace v where
addVs :: v -> v -> v
scaleV :: Double -> v -> v
instance GVecSpace (G.V1 a) where
addVs _ _ = undefined
scaleV _ _ = undefined
instance GVecSpace (G.U1 a) where
addVs _ x = x -- no value
scaleV _ x = x -- no value
instance (GVecSpace (f a), GVecSpace (g a)) => GVecSpace ((f :+: g) a) where
addVs (L1 x) (L1 y) = L1 $ addVs x y
addVs (R1 x) (R1 y) = R1 $ addVs x y
scaleV d (L1 x) = L1 $ scaleV d x
scaleV d (R1 x) = R1 $ scaleV d x
instance (GVecSpace (f a), GVecSpace (g a)) => GVecSpace ((f :*: g) a) where
addVs (x1 :*: x2) (y1 :*: y2) =
addVs x1 y1 :*: addVs x2 y2
scaleV d (x1 :*: x2) =
scaleV d x1 :*: scaleV d x2
instance (GVecSpace c) => GVecSpace (K1 i c p) where
addVs (K1 x) (K1 y) = K1 $ addVs x y
scaleV d (K1 x) = K1 $ scaleV d x
instance (GVecSpace (f p)) => GVecSpace (M1 i c f p) where
addVs (M1 x) (M1 y) = M1 $ addVs x y
scaleV d (M1 x) = M1 $ scaleV d x
instance (Generic a, GVecSpace (Rep a)) => GVecSpace a where
addVs x y =
G.to $ addVs (G.from x) (G.from y)
scaleV d x =
G.to $ scaleV d (G.from x)
但是 GHC 抱怨是因为 Rep a
有错误的种类:
Expecting one more argument to ‘Rep a’
The first argument of ‘GVecSpace’ should have kind ‘*’,
but ‘Rep a’ has kind ‘* -> *’
In the instance declaration for ‘GVecSpace a’
我应该更改什么才能使其正常工作?一种选择是使 GVecSpace
仅适用于 * -> *
的种类,但这看起来很尴尬。有没有办法避免这种情况?
要创建一个使用 GHC.Generics
的库,我们首先需要一些先决条件。
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
import GHC.Generics as G
泛型的所有表示都带有一个名为 "the parameter" p
的额外类型参数。您可以在 Generic a
class、type Rep a :: * -> *
中的类型 Rep a
中看到这一点。数据类型的表示不仅仅是另一种数据类型,它是一种类型 * -> *
,与 Functor
s 和 Monad
s 相同。它以另一种类型作为参数。大多数时候,根据通用表示定义 class 的实例,我们将忽略参数。
由于额外的参数,定义一个非通用的 class 很有用。我们稍后会添加更多内容。
class VecSpace v where
addVs :: v -> v -> v
scaleV :: Double -> v -> v
...
class、GVecSpace
的通用版本有一个关于所有值类型的额外参数 a
。我们之前在所有地方使用 v
,我们将使用 f a
。我们将通过在 VecSpace
的名称前加上 g
来为 GVecSpace
创建新名称。
class GVecSpace f where
gaddVs :: f a -> f a -> f a
gscaleV :: Double -> f a -> f a
GVecSpace
class 有点笨拙,只适用于 * -> *
类型,但它仅用于制作 VecSpace
的默认实现。您将在其他任何地方使用 VecSpace
。
只有一个构造函数的单元类型是向量 space。请注意,G.U1
未应用于参数。
instance GVecSpace G.U1 where
gaddVs _ x = x -- no value
gscaleV _ x = x -- no value
两个向量space的乘积是一个向量space。请注意,f
和 g
以及 f :*: g
不适用于参数类型。
instance (GVecSpace f, GVecSpace g) => GVecSpace (f :*: g) where
gaddVs (x1 :*: x2) (y1 :*: y2) =
gaddVs x1 y1 :*: gaddVs x2 y2
gscaleV d (x1 :*: x2) =
gscaleV d x1 :*: gscaleV d x2
对于K1
,我们从类型中删除最后一个参数p
,并根据非泛型VecSpace
来定义它。 c
参数只有kind*
,是普通类型,不可能是GVecSpace
.
instance (VecSpace c) => GVecSpace (K1 i c) where
gaddVs (K1 x) (K1 y) = K1 $ addVs x y
gscaleV d (K1 x) = K1 $ scaleV d x
对于 M1
元数据节点,我们从类型中删除最终参数 p
。
instance (GVecSpace f) => GVecSpace (M1 i c f) where
gaddVs (M1 x) (M1 y) = M1 $ gaddVs x y
gscaleV d (M1 x) = M1 $ gscaleV d x
现在我们可以 return 到 VecSpace
class 并填写当它的表示有 GVecSpace
时如何成为 VecSpace
的默认值实例。我们将参数转换为表示 from
类型 v
,对表示执行操作的泛型版本,然后在我们“大功告成。
class VecSpace v where
addVs :: v -> v -> v
scaleV :: Double -> v -> v
default addVs :: (Generic v, GVecSpace (Rep v)) => v -> v -> v
addVs x y = to (gaddVs (from x) (from y))
default scaleV :: (Generic v, GVecSpace (Rep v)) => Double -> v -> v
scaleV s = to . gscaleV s . from
使用
假设您已经观察到 Double
s 形成一个向量 space
instance VecSpace Double where
addVs = (+)
scaleV = (*)
我们可以根据 VecSpace
.
default
派生元组的工作 VecSpace
实例
instance (VecSpace a, VecSpace b) => VecSpace (a, b)