Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 这是什么';约束';什么意思?_Haskell_Type Families - Fatal编程技术网

Haskell 这是什么';约束';什么意思?

Haskell 这是什么';约束';什么意思?,haskell,type-families,Haskell,Type Families,在这段代码中,我试图使我的辅助函数go中的第一个参数成为“type family”类型。我看到在类型中,类似的insert函数属于类型类,而在下面的示例中,它不属于类型类 我是一个新类型的家庭,所以可能我用错了,但这个错误意味着什么 {-# LANGUAGE TypeFamilies #-} -- | key class K a where -- | iterator for key type I a :: * mkI :: a -> I a --| A map data

在这段代码中,我试图使我的辅助函数
go
中的第一个参数成为“type family”类型。我看到在类型中,类似的
insert
函数属于类型类,而在下面的示例中,它不属于类型类

我是一个新类型的家庭,所以可能我用错了,但这个错误意味着什么

{-# LANGUAGE TypeFamilies #-}

-- | key
class K a where
  -- | iterator for key
  type I a :: *
  mkI :: a -> I a

--| A map
data (K a) => M a b = M a b

insert :: (K a) => a -> b -> M a b -> M a b
insert = go mkI    -- <<< PROBLEM
  where
    go o a b m = m
可能修复:添加修复的类型签名 这些类型变量

这包括:

{-# LANGUAGE TypeFamilies, GADTs, ScopedTypeVariables #-}

-- | key
class K a where
  -- | iterator for key
  type I a :: *
  mkI :: a -> I a

-- | A map
data M x y where
    M :: K a => a -> b -> M a b

insert :: forall a b. (K a) => a -> b -> M a b -> M a b
insert = go mkI
  where
    go :: (a -> I a) -> a -> b -> M a b -> M a b
    go o a b m = m
我改变了什么?为什么

首先,我假设您希望在
M
上使用约束,因此我使用了一种类型定义形式来强制约束并使其在使用站点可用,即
GADT


第二,你的GHC抱怨的问题,模棱两可。关键是编译器无法推断出它应该使用哪个
mkI
,所以我们必须告诉它。为此,我们必须将使用的类型变量引入作用域,然后在本地签名中告诉编译器要使用哪种类型实例。

首先,请注意,数据类型上下文(
data(ka)=>ma b=ma b
)已从语言中删除,并且从未有用过。现在看看其他东西。您好,您如何将“go”变成顶级函数?@cdupont您只需将其移动到顶级,并将约束添加到类型签名中,
go::(ka)=>(a->ia)->a->b->M a b->M a b
。不过,我不知道这对什么有用。在这种情况下,
insert
中的
a
b
go
中会有所不同。。。这就是您添加forall no的原因?@cdupont从
insert
传递的参数将确定使用的
a
b
类型。在
insert
范围内引用这些类型时,需要使用
forall
。在顶层,类型签名中的类型独立于
insert
的类型,但是参数的传递将确保被调用的
go
实例使用相同的类型。
{-# LANGUAGE TypeFamilies, GADTs, ScopedTypeVariables #-}

-- | key
class K a where
  -- | iterator for key
  type I a :: *
  mkI :: a -> I a

-- | A map
data M x y where
    M :: K a => a -> b -> M a b

insert :: forall a b. (K a) => a -> b -> M a b -> M a b
insert = go mkI
  where
    go :: (a -> I a) -> a -> b -> M a b -> M a b
    go o a b m = m