Haskell中的函数对象编译错误

Cli*_*ton 1 haskell function-object

我正在尝试创建一个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)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

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)
Run Code Online (Sandbox Code Playgroud)

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

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

lef*_*out 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)
Run Code Online (Sandbox Code Playgroud)

或者你有什么特别的理由喜欢fundeps而不是类型系列吗?