Haskell - 形式A的所有函数 - > A - > ... - > A.

Rhu*_*ndC 6 haskell

我有一个类型(称之为A),我想创建类型为A的函数的类型类 - > A,A - > A - > A,A - > A - > A - > ...等等工作:

{-# LANGUAGE FlexibleInstances #-}

data A = A

class AsToA a where
  takeA :: AsToA b => a -> A -> Either A b

instance AsToA (A -> A) where
  takeA f a = Left (f a)

instance AsToA b => AsToA (A -> b) where
  takeA f a = Right (f a)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误消息:

AsToA.hs:12:22:
    Couldn't match expected type ‘b1’ with actual type ‘b’
      ‘b’ is a rigid type variable bound by
          the instance declaration at AsToA.hs:11:10
      ‘b1’ is a rigid type variable bound by
          the type signature for

             takeA :: AsToA b1 => (A -> b) -> A -> Either A b1
          at AsToA.hs:12:3
    Relevant bindings include
      f :: A -> b (bound at AsToA.hs:12:9)
      takeA :: (A -> b) -> A -> Either A b1 (bound at AsToA.hs:12:3)
    In the first argument of ‘Right’, namely ‘(f a)’
    In the expression: Right (f a)
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?非常感谢任何建议.

Ørj*_*sen 2

正如对另一个答案的评论中提到的,您可能并不真正需要Either, 然后takeA基本上总是id,只是有类型限制。如果是这样,您可以将其设为无方法类:

{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}

data A = A

class AsToA a

takeA :: AsToA a => a -> a
takeA = id

instance AsToA (A -> A)

instance AsToA (A -> b) => AsToA (A -> (A -> b))
Run Code Online (Sandbox Code Playgroud)

或者,您可能希望将函数转换为允许您动态传入As 的通用类型。如果这样Either还不够,但您可以定义自己的:

{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}

data A = A

data R = Result A | MoreArgs (A -> R)

class AsToA a where
    takeA :: a -> A -> R

instance AsToA (A -> A) where
    takeA f a = Result (f a)

instance AsToA (A -> b) => AsToA (A -> (A -> b)) where
    takeA f a = MoreArgs (takeA $ f a)
Run Code Online (Sandbox Code Playgroud)