Flip数据类型的Functor类型变量

时间:2017-07-04 14:04:26

标签: haskell arguments functor newtype

我有以下类型定义:

newtype Flip f a b = 
  Flip (f b a) deriving (Eq, Show)

Flip数据构造函数是否有一个或三个参数?

Consinder实施后:

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)的类型是什么?

2 个答案:

答案 0 :(得分:7)

import django.http from django.views.generic import View from project.stuff.models import Stuff class ApiStuff(View): @staticmethod def get(request, *args, **kwargs): stuff_id = kwargs['stuff_id'] try: stuff = Stuff.objects.get(pk=stuff_id) except Stuff.DoesNotExist: return response({"error": "stuff not found"}, 404) result = stuff.serialize() return response(result) def response(data, status=200): data = json.dumps(data) return django.http.HttpResponse(data, status=status, content_type='application/json') 数据构造函数有一个参数。该参数的类型为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的类型是什么?

(Flip K a)不是完全应用的类型。在伪代码中,它具有类型Flip K a。解析b -> Flip K a b后(b使用更高阶类型),我们知道Functor的唯一参数将具有Flip构造函数。因此,例如K bFlip (K 1)类型。

答案 1 :(得分:6)

现在,未来(使用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

类型构造函数Flip有两个隐式参数,即kk1,以及三个显式参数,是生成类型的二元函数,然后它的两个参数的顺序相反。这个函数的参数是无约束的类型(老人们可以说&#34;亲和&#34;如果他们喜欢),但它肯定会返回一个类型(严格意义上的{&1;} * &#34;而不是对::&#34;)的任何旧垃圾权利的无用模糊感,因为它肯定在MkFlip的声明中用作类型。< / p>

数据构造函数MkFlip采用五个隐式参数(正好是Flip的参数)和一个显式参数,是一些数据在f b a

正在进行的是Hindley-Milner类型推断一级。收集约束(例如,f b a必须居住*,因为构造函数参数必须居住f b a),否则会传递最常规的类型:ab可以是任何内容,因此它们的类型被概括为k1k

让我们使用常量类型构造函数玩相同的游戏:

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的参数,该参数成为第一个 K的参数,因此是存储元素的类型。

基于统一的类型推断是活生生的,并且(相当)很好,在::右边。

相关问题