0

私はこのようなクラスを書きたいです:

class C c where
    op :: c -> c -> Bool

class A b => B b where
    func :: C c => b -> c -- ^ type 'c' is random(forall). 
    func2 :: b -> b -> Bool
    func2 x y = func b `op` func c

ここで、cはによって制限される型でCあり、この制限は func2 で使用されます。しかし、これはコンパイラではありません。型cは実数型ではありません。を追加forallまたは使用しようとしましTypeFamiliesたが、誰もこれを行うことができません。TypeFamilies良さそうに見えますが、C c => b -> c`type X x :: C * => *.

(A b, C c) => B b cこのクラスを定義するために使用する必要がありますか? B like を使用する別のクラスがありB b => D d bます。クラス B のパラメーターを追加する場合、D クラスにももう 1 つのパラメーターが必要です。実際、Seq aは classDで使用されますが、これは と一致しませんD d b

編集:もう1つの説明。

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Main where

type Ta = (Integer, Integer)
newtype Tb t = Tb { tb :: [t] } deriving Show

class Eq a => A a where
    a1f :: Ord b => a -> b
    a2f :: a -> a -> Bool
    a2f x y = a1f x >= a1f y

instance A Ta where
    a1f (_, y) = y

class A a => B b a where
    op :: b a -> b a

instance B Tb Ta where
    op x = x

main :: IO ()
main = putStrLn $ show $ op $ (Tb [(1, 1)] :: Tb Ta)

コンパイラは次の行に文句を言いますa2f :: b -> Bool

    • Could not deduce (Ord a0) arising from a use of ‘>=’
      from the context: A a
        bound by the class declaration for ‘A’ at test.hs:10:15
      The type variable ‘a0’ is ambiguous
      These potential instances exist:
        instance Ord Ordering -- Defined in ‘GHC.Classes’
        instance Ord Integer
          -- Defined in ‘integer-gmp-1.0.2.0:GHC.Integer.Type’
        instance Ord a => Ord (Maybe a) -- Defined in ‘GHC.Maybe’
        ...plus 22 others
        ...plus four instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression: a1f x >= a1f y
      In an equation for ‘a2f’: a2f x y = a1f x >= a1f y

EDIT2: 型ファミリーを使用する

...
class Eq a => A a where
    type AT a :: *
    a1f :: Ord (AT a) => a -> AT a
    a2f :: a -> a -> Bool
    a2f x y = a1f x >= a2f y

instance A Ta where
    type AT Ta = Integer
    a1f (_, y) = y
...

次のエラーが表示されます。

    • Could not deduce (Ord (AT a)) arising from a use of ‘>=’
      from the context: A a
        bound by the class declaration for ‘A’ at test.hs:10:15
    • In the expression: a1f x >= a1f y
      In an equation for ‘a2f’: a2f x y = a1f x >= a1f y
4

2 に答える 2

1

現状のコードでは、問題は単純にcinfunc b `op` func cambiguousであることです。これはそれほど問題ではありません。ローカル署名で選択を特定するだけです。例えば

func2 x y = func x `op` (func y :: Int)

しかし、これはあなたが本当に望んでいるものではないかもしれません。c本当にクラスの型パラメーターであるべきかfunc、それともインスタンス全体の型パラメーターであるべきか? 後者の場合、MPTC が適切なアプローチになります。

{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes, TypeApplications #-}

class ∀ b c . (A b, C c) => B b c where
  func :: b -> c
  func2 :: b -> b -> Bool
  func2 x y = func @b @c b `op` func c

または、インスタンスごとに 1 つだけc意味がある場合は、型ファミリまたは Fundep が必要です。

{-# LANGUAGE TypeFamilies #-}

class A b => B b where
  type Ct b :: *
  func :: b -> Ct b
  func2 :: b -> b -> Bool
  func2 x y = func b `op` func c
于 2019-09-23T12:32:19.183 に答える