1

I'm trying to create a class Func which represents a function, and then a data type Dot which composes functions. Below is my attempt, but I'm getting compile errors:

{-# 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)

I get the following errors:

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)

What do I need to fix to make this compile?

I realise this might seem a bit silly, but I thought it might be useful to be able to carry around different functions as unique types, as one could perhaps attach various metadata to those types (I'm not sure exactly what yet).

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 を適用)

は、任意のタイプのインスタンスを持っていることを示しておりa、これらは とは関係なく、の構築に使用されます。bDotabDot

インスタンス宣言にコンテキスト(Func f1 a b, Func f2 b c)を追加すると、ghc-7.2 でコンパイルされますが、7.4 または 7.6 ではコンパイルされません。

aタイプおよびcをタイプ パラメータとして に追加すると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 に答える