Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.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_Interface_Typeclass_Abstraction - Fatal编程技术网

具有参数化类型的Haskell类型类

具有参数化类型的Haskell类型类,haskell,interface,typeclass,abstraction,Haskell,Interface,Typeclass,Abstraction,我想定义一个特定的函子,如下所示: {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-} data ValOrError a b = Val a | Error b class MF c a b where mcons :: a -> c -> c merr :: b -> c mhead :: c -> ValOrError a b mtail :: c -

我想定义一个特定的函子,如下所示:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}

data ValOrError a b = Val a | Error b

class MF c a b where
  mcons :: a -> c -> c
  merr :: b -> c
  mhead :: c -> ValOrError a b
  mtail :: c -> ValOrError c b
mfilter f e =
  let h = mhead e in
  let t = mtail e in
  case h of
    Error b -> e
    Val a -> case (f a) of
      True -> case t of
        Error d -> mcons a (merr d)
        Val b -> mcons a (mfilter f b)
      False -> case t of
        Error d -> merr d
        Val b -> mfilter f b
我希望type
c
上的typeclass
MF
具有类型参数
a
b
。我尝试在这样的数据结构上定义一个过滤函数,如下所示:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}

data ValOrError a b = Val a | Error b

class MF c a b where
  mcons :: a -> c -> c
  merr :: b -> c
  mhead :: c -> ValOrError a b
  mtail :: c -> ValOrError c b
mfilter f e =
  let h = mhead e in
  let t = mtail e in
  case h of
    Error b -> e
    Val a -> case (f a) of
      True -> case t of
        Error d -> mcons a (merr d)
        Val b -> mcons a (mfilter f b)
      False -> case t of
        Error d -> merr d
        Val b -> mfilter f b
但我得到了以下错误:

haskell.hs:24:1:

Could not deduce (MF c a2 b3)
  arising from the ambiguity check for ‘mfilter’
from the context (MF c a5 b6,
                  MF c a4 b5,
                  MF c a4 b4,
                  MF c a4 b,
                  MF c a3 b6,
                  MF c a b6)
  bound by the inferred type for ‘mfilter’:
             (MF c a5 b6, MF c a4 b5, MF c a4 b4,
              MF c a4 b, MF c a3 b6, MF c a b6) =>
             (a4 -> Bool) -> c -> c
  at haskell.hs:(24,1)-(35,28)
The type variables ‘a2’, ‘b3’ are ambiguous
When checking that ‘mfilter’
  has the inferred type ‘forall b c a b1 a1 a2 b2 a3 b3.
                         (MF c a3 b3, MF c a2 b2, MF c a2 b1,
                          MF c a2 b, MF c a1 b3, MF c a b3) =>
                         (a2 -> Bool) -> c -> c’
Probable cause: the inferred type is ambiguous
我想知道在haskell中是否有更好的方法来说明类型
c
总是将
a
b
作为类型参数。使用类似Java的语法:

public interface MF<A,B> {
   MF<A,B> mcons(A head, MF<A,B> tail);
   MF<A,B> merr(B error);
   ValOrError<A,B> head(MF<A,B> e);
   ValOrError<MF<A,B>,B> tail(MF<A,B> e);
}

从代码开始,最直接的方法是向类型类添加函数依赖项:

{-# LANGUAGE FunctionalDependencies #-}
class MF c a b | c -> a, c -> b where
  ...
这基本上只是告诉编译器,
a
b
的类型信息已经包含在
c
中(因此可以在调用站点提取,因此
a2
b3
等不会含糊不清)。定义
实例MF
时,GHC可以确定如何准确提取此信息。虽然这通常效果很好,但我发现你为什么要这样做有点疑问:如果
c
总是有
xab
的形式(而且
X
是一个适当的
数据类型的函数,可以部分应用),那么为什么还要在类标题中提到
a
b
?它们基本上是多余的。为什么不给类一个单独的参数(类型为
Type->Type->Type
),然后应用于
a
b

class MF x where
  mcons :: a -> x a b -> x a b
  merr :: b -> x a b
  mhead :: x a b -> ValOrError a b
  mtail :: x a b -> ValOrError (x a b) b
或者,如果您确实希望
c
具有种类
Type
(这确实有道理!),我建议将
a
b
类型作为类型族存放在类定义中:

{-# LANGUAGE TypeFamilies #-}
class MF c where
  type ValType c :: *
  type ErrType c :: *
  mcons :: ValType c -> c -> c
  merr :: ErrType c -> c
  mhead :: c -> ValOrError (ValType c) (ErrType c)
  mtail :: c -> ValOrError c (ErrType c)

这基本上等同于
TypeFamilies
解决方案,但提供了一个更明确、更不神秘(尽管也更详细)的接口。

我有一个关于最后一个解决方案的问题,我最喜欢这个解决方案。如果我有以下数据
data MemoryMonad a b=Lift b | Guard b | Elem a(MemoryMonad a b)
;类型ErrType(MemoryMonad a b)=b