Flip 数据类型的函子类型变量
Functor type variables for Flip data type
我有以下类型定义:
newtype Flip f a b =
Flip (f b a) deriving (Eq, Show)
Flip
数据构造函数有一个或三个参数吗?
考虑以下实施:
data K a b = K a
newtype Flip f a b =
Flip (f b a) deriving (Eq, Show)
instance Functor (Flip K a) where
fmap f (Flip (K b)) = Flip (K (f b))
(Flip K a)
的类型是什么?
Flip
数据构造函数有 一个参数。该参数的类型为 f b a
.
这意味着 f
本身是类型为 f :: * -> * -> *
的高阶类型参数。更严格的 newtype
语句是:
newtype Flip (f :: * -> * -> *) a b = Flip (f b a)
因此,您可以实例化一个 Flip Either Int Bool
,因为 Either
是一个需要两个额外类型参数的类型,然后构造一个 Flip (Right 1) :: Flip Either Int Bool
.
What is the type of (Flip K a)
?
Flip K a
不是完全应用的类型。在伪代码中,它的类型是b -> Flip K a b
。一旦 b
被解析(Functor
适用于高阶类型),我们知道 Flip
的唯一参数将有一个 K b
构造函数。因此,例如 Flip (K 1)
是 Flip K a Int
类型。
未来就是现在,当您(使用 ghc 8 和)打开一两个标志时
Prelude> :set -XPolyKinds -XFlexibleInstances
让我们声明
Prelude> newtype Flip f a b = MkFlip (f b a)
然后查询
Prelude> :kind Flip
Flip :: (k1 -> k -> *) -> k -> k1 -> *
Prelude> :type MkFlip
MkFlip
:: forall k k1 (b :: k) (f :: k -> k1 -> *) (a :: k1).
f b a -> Flip f a b
type 构造函数 Flip
接受两个隐式参数,即 k
和 k1
,以及三个显式参数,即二元函数生成一个类型,然后以相反的顺序生成它的两个参数。这个函数的参数是unconstrained类型的(老人们喜欢可以说"kind"),但肯定是returns类型(严格意义上的"thing in *
",而不是无用的"any old rubbish right of ::
") 的模糊意义,因为它肯定在 MkFlip
.
的声明中用作类型
data 构造函数 MkFlip
采用 5 个隐式参数(正是 Flip
的参数)和一个显式参数,是 f b a
.
中的一些数据
正在进行的是 Hindley-Milner 类型推理的上一层。收集约束(例如,f b a
必须位于 *
,因为构造函数参数必须位于 f b a
),否则会提供最通用的类型:a
和 b
可以是任何东西,所以它们的类型被概括为 k1
和 k
.
让我们用常量类型构造函数玩同样的游戏:
Prelude> newtype K a b = MkK a
Prelude> :kind K
K :: * -> k -> *
Prelude> :type MkK
MkK :: forall k (b :: k) a. a -> K a b
我们看到 a :: *
但 b
可以是任何旧垃圾(就此而言,k :: *
,如今,* :: *
)。显然,a
实际上是作为事物的类型使用的,但是b
根本没有被使用,因此不受约束。
然后我们可以声明
Prelude> instance Functor (Flip K b) where fmap f (MkFlip (MkK a)) = MkFlip (MkK (f a))
然后问
Prelude> :info Flip
...
instance [safe] forall k (b :: k). Functor (Flip K b)
这告诉我们未使用的 b
仍然可以是任何旧垃圾。因为我们有
K :: * -> k -> *
Flip :: (k1 -> k -> *) -> k -> k1 -> *
我们可以统一k1 = *
得到
Flip K :: k -> * -> *
等等
Flip K b :: * -> *
对于任何旧的 b
。因此,一个 Functor
实例是合理的,并且确实是可交付的,函数作用于打包的 a
元素,对应于 Flip K b
的参数,成为 first K
的参数,因此是存储元素的类型。
基于统一的类型推断仍然存在并且(相当)好,::
。
我有以下类型定义:
newtype Flip f a b =
Flip (f b a) deriving (Eq, Show)
Flip
数据构造函数有一个或三个参数吗?
考虑以下实施:
data K a b = K a
newtype Flip f a b =
Flip (f b a) deriving (Eq, Show)
instance Functor (Flip K a) where
fmap f (Flip (K b)) = Flip (K (f b))
(Flip K a)
的类型是什么?
Flip
数据构造函数有 一个参数。该参数的类型为 f b a
.
这意味着 f
本身是类型为 f :: * -> * -> *
的高阶类型参数。更严格的 newtype
语句是:
newtype Flip (f :: * -> * -> *) a b = Flip (f b a)
因此,您可以实例化一个 Flip Either Int Bool
,因为 Either
是一个需要两个额外类型参数的类型,然后构造一个 Flip (Right 1) :: Flip Either Int Bool
.
What is the type of
(Flip K a)
?
Flip K a
不是完全应用的类型。在伪代码中,它的类型是b -> Flip K a b
。一旦 b
被解析(Functor
适用于高阶类型),我们知道 Flip
的唯一参数将有一个 K b
构造函数。因此,例如 Flip (K 1)
是 Flip K a Int
类型。
未来就是现在,当您(使用 ghc 8 和)打开一两个标志时
Prelude> :set -XPolyKinds -XFlexibleInstances
让我们声明
Prelude> newtype Flip f a b = MkFlip (f b a)
然后查询
Prelude> :kind Flip
Flip :: (k1 -> k -> *) -> k -> k1 -> *
Prelude> :type MkFlip
MkFlip
:: forall k k1 (b :: k) (f :: k -> k1 -> *) (a :: k1).
f b a -> Flip f a b
type 构造函数 Flip
接受两个隐式参数,即 k
和 k1
,以及三个显式参数,即二元函数生成一个类型,然后以相反的顺序生成它的两个参数。这个函数的参数是unconstrained类型的(老人们喜欢可以说"kind"),但肯定是returns类型(严格意义上的"thing in *
",而不是无用的"any old rubbish right of ::
") 的模糊意义,因为它肯定在 MkFlip
.
data 构造函数 MkFlip
采用 5 个隐式参数(正是 Flip
的参数)和一个显式参数,是 f b a
.
正在进行的是 Hindley-Milner 类型推理的上一层。收集约束(例如,f b a
必须位于 *
,因为构造函数参数必须位于 f b a
),否则会提供最通用的类型:a
和 b
可以是任何东西,所以它们的类型被概括为 k1
和 k
.
让我们用常量类型构造函数玩同样的游戏:
Prelude> newtype K a b = MkK a
Prelude> :kind K
K :: * -> k -> *
Prelude> :type MkK
MkK :: forall k (b :: k) a. a -> K a b
我们看到 a :: *
但 b
可以是任何旧垃圾(就此而言,k :: *
,如今,* :: *
)。显然,a
实际上是作为事物的类型使用的,但是b
根本没有被使用,因此不受约束。
然后我们可以声明
Prelude> instance Functor (Flip K b) where fmap f (MkFlip (MkK a)) = MkFlip (MkK (f a))
然后问
Prelude> :info Flip
...
instance [safe] forall k (b :: k). Functor (Flip K b)
这告诉我们未使用的 b
仍然可以是任何旧垃圾。因为我们有
K :: * -> k -> *
Flip :: (k1 -> k -> *) -> k -> k1 -> *
我们可以统一k1 = *
得到
Flip K :: k -> * -> *
等等
Flip K b :: * -> *
对于任何旧的 b
。因此,一个 Functor
实例是合理的,并且确实是可交付的,函数作用于打包的 a
元素,对应于 Flip K b
的参数,成为 first K
的参数,因此是存储元素的类型。
基于统一的类型推断仍然存在并且(相当)好,::
。