[英]Haskell - All functions of form A -> A -> … -> A
I have a type (call it A) and I want to make a typeclass of the functions of type A -> A, A -> A -> A, A -> A -> A -> ... etc. This doesn't work: 我有一个类型(称之为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)
I get the following error message: 我收到以下错误消息:
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)
Any ideas? 有任何想法吗? Thanks very much for any advice. 非常感谢任何建议。
There is some confusion between the two b
s: 两个b
之间存在一些混淆:
class AsToA a where
takeA :: AsToA b => a -> A -> Either A b
instance AsToA b => AsToA (A -> b) where
takeA f a = Right (f a)
These are not the same. 这些都不一样。 Let's rename the first one to c
让我们将第一个重命名为c
class AsToA a where
takeA :: AsToA c => a -> A -> Either A c
instance AsToA b => AsToA (A -> b) where
takeA f a = Right (f a)
Now, Right (fa)
has type Either A b
but should have type Either A c
for any c
such that AsToA c
holds. 现在, Right (fa)
类型为Either A b
但应该具有类型Either A c
任何c
Either A c
,以便AsToA c
成立。 This does not type check. 这不是类型检查。
The issue here is that the signature 这里的问题是签名
takeA :: AsToA c => a -> A -> Either A c
promises that takeA
can return Either A c
for any c
, caller's choice. 承诺, takeA
可以返回Either A c
任何 c
,来电者的选择。 This is not what you want, I guess. 我想这不是你想要的。
I'm still not sure about what the actual intended result is, but I guess the problem is similar to the following one. 我仍然不确定实际的预期结果是什么,但我猜这个问题类似于下面的问题。
Given a function
f
of typeA->A->...->A
return a function\\x -> fxx ...
, with one application ofx
for each->
in the type (hence of typeA->A
). 给定类型为A->A->...->A
的函数f
A->A->...->A
返回一个函数\\x -> fxx ...
,每个应用一个x
->
类型(因此类型A->A
)。
A possible solution is 可能的解决方案是
{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}
data A = A -- could be anything
class C f where
takeA :: f -> A -> A
instance C (A -> A) where
takeA f = f
instance C b => C (A -> b) where
takeA f = \x -> takeA (f x) x
Note that this requires OverlappingInstances
to be used, which is quite evil . 请注意,这需要使用OverlappingInstances
,这是非常邪恶的 。 I'd recommend to avoid it. 我建议避免它。
To avoid it, in this case it's enough to define an instance even for the type A
. 为了避免这种情况,在这种情况下,甚至为类型A
定义一个实例也足够了。
{-# LANGUAGE FlexibleInstances #-}
data A = A -- could be anything
class C f where
takeA :: f -> A -> A
instance C A where
takeA a = \_ -> a
instance C b => C (A -> b) where
takeA f = \x -> takeA (f x) x
As mentioned in the comments to the other answer, you might not really need the Either
, and takeA
is then basically always id
, just with a type restriction. 正如对其他答案的评论中所提到的,你可能并不真的需要Either
,而takeA
则基本上都是id
,只是带有类型限制。 If so you can make this a method-less class: 如果是这样,你可以把它变成一个无方法的类:
{-# 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))
Alternatively, you might want to convert the functions to a common type that allows you to pass in A
s dynamically. 或者,您可能希望将函数转换为允许您动态传入A
的公共类型。 If so Either
won't be enough, but you can define your own: 如果是这样, 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.