1

我正在尝试创建一个Func表示函数的类,然后创建一个Dot组成函数的数据类型。以下是我的尝试,但出现编译错误:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE GADTs #-}

module Func where
  class Func f a b | f -> a, f -> b where
    apply :: f -> a -> b

  data Dot f1 f2 where
    Dot :: (Func f1 a b, Func f2 b c) => f1 -> f2 -> Dot f1 f2

  instance Func (Dot f1 f2) a c where
    apply (Dot f1 f2) = (apply f2) . (apply f1)

我收到以下错误:

Func.hs:15:26:
    Could not deduce (Func f2 b c) arising from a use of `apply'
    from the context (Func f1 a1 b, Func f2 b c1)
      bound by a pattern with constructor
                 Dot :: forall f1 f2 a b c.
                        (Func f1 a b, Func f2 b c) =>
                        f1 -> f2 -> Dot f1 f2,
               in an equation for `apply'
      at Func.hs:15:12-20
    Possible fix:
      add (Func f2 b c) to the context of
        the data constructor `Dot'
        or the instance declaration
    In the first argument of `(.)', namely `(apply f2)'
    In the expression: (apply f2) . (apply f1)
    In an equation for `apply':
        apply (Dot f1 f2) = (apply f2) . (apply f1)

Func.hs:15:39:
    Could not deduce (Func f1 a b) arising from a use of `apply'
    from the context (Func f1 a1 b, Func f2 b c1)
      bound by a pattern with constructor
                 Dot :: forall f1 f2 a b c.
                        (Func f1 a b, Func f2 b c) =>
                        f1 -> f2 -> Dot f1 f2,
               in an equation for `apply'
      at Func.hs:15:12-20
    Possible fix:
      add (Func f1 a b) to the context of
        the data constructor `Dot'
        or the instance declaration
    In the second argument of `(.)', namely `(apply f1)'
    In the expression: (apply f2) . (apply f1)
    In an equation for `apply':
        apply (Dot f1 f2) = (apply f2) . (apply f1)

我需要修复什么才能编译?

我意识到这可能看起来有点傻,但我认为能够将不同的功能作为独特的类型进行携带可能很有用,因为可以将各种元数据附加到这些类型(我还不确定到底是什么)。

4

2 回答 2

5

问题是实例负责人Func (Dot f1 f2) a c无法“查看”f1f2推断出功能依赖关系。您需要自己执行此操作,使用等效公式更容易

{-# LANGUAGE TypeFamilies      #-}

class Func f where
  type FuncArg f :: *
  type FuncRes f :: *
  apply :: f -> FuncArg f -> FuncRes f

data Dot f1 f2 where
  Dot :: (Func f1, Func f2, FuncArg f2~FuncRes f1)
                                 => f1 -> f2 -> Dot f1 f2

instance Func (Dot f1 f2) where
  type FuncArg (Dot f1 f2) = FuncArg f1
  type FuncRes (Dot f1 f2) = FuncRes f2
  apply (Dot f1 f2) = (apply f2) . (apply f1)

或者你有什么特别的理由更喜欢fundeps而不是类型家庭?

于 2013-01-05T14:37:38.140 回答
4

错误的直接原因是

实例 Func (Dot f1 f2) ac where apply (Dot f1 f2) = (apply f2) 。(应用 f1)

说你有一个任何类型的实例abwith Dot,这些ab用于构造Dot.

将上下文添加(Func f1 a b, Func f2 b c)到实例声明使其可以使用 ghc-7.2 编译,但不能使用 7.4 或 7.6。

将类型ac作为类型参数添加到Dot,

data Dot f1 f2 a c where
  Dot :: (Func f1 a b, Func f2 b c) => f1 -> f2 -> Dot f1 f2 a c

使它与所有这些 GHC 一起编译。

于 2013-01-05T14:36:51.650 回答