Haskell 使用TypeClass提升多态值
我试图实现自动提升到Haskell 使用TypeClass提升多态值,haskell,typeclass,Haskell,Typeclass,我试图实现自动提升到类型中的任一类型:纯值 使用右侧解除,已使用id值解除 -- Wrapper for pure, non-Either values newtype ConstRight a = ConstRight a class LiftEither t e a where liftEither :: t -> Either e a instance LiftEither (Either e a) e a where liftEither = id instance
类型中的任一类型:纯值
使用右侧
解除,已使用id
值
解除
-- Wrapper for pure, non-Either values
newtype ConstRight a = ConstRight a
class LiftEither t e a where
liftEither :: t -> Either e a
instance LiftEither (Either e a) e a where
liftEither = id
instance LiftEither (ConstRight a) e a where
liftEither (ConstRight a) = Right a
x :: Either () (Int -> Int)
x = liftEither $ ConstRight (id :: Int -> Int)
y :: Either () (a -> a)
y = liftEither $ ConstRight id
z :: Either (a -> a) ()
z = liftEither $ Left id
但是,使用此方法只能提升单体值。这个
y
和z
产量类型错误的定义:
No instance for (LiftEither (ConstRight (a1 -> a1)) () (a -> a))
arising from a use of ‘liftEither’
The type variable ‘a1’ is ambiguous
No instance for (LiftEither (Either (a0 -> a0) b0) (a -> a) ())
arising from a use of ‘liftEither’
The type variables ‘b0’, ‘a0’ are ambiguous
这可以通过功能依赖性来解决,但是ConstRight a
不能确定e
:
class LiftEither t e a | t -> e a where
liftEither :: t -> Either e a
我也尝试过使用关联类型,但我找不到合适的
ConstRight
实例的定义:
class LiftEither t where
type Result t
liftEither :: t -> Result t
instance LiftEither (Either e a) where
type Result (Either e a) = Either e a
liftEither = id
instance LiftEither (ConstRight a) where
type Result (ConstRight a) = Either e a -- e is not in scope
liftEither (ConstRight a) = Right a
是否可以为多态值实现此功能?您应该始终将尽可能多的信息从实例头移动到实例约束。在这里,可以纯粹根据我们是否有
或ConstRight
来确定正确的实例,因此不需要进一步约束实例头
LiftEither(ea)ea
过于严格,因为它要求两个a
-s和两个e
-s可以在匹配实例头的点处被确定为相等。另一个实例也有同样的问题。相反,您应该将类型等式移动到约束。这样GHC就可以愉快地匹配实例,并在以后尝试解决约束
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances #-}
newtype ConstRight a = ConstRight a
class LiftEither t e a where
liftEither :: t -> Either e a
instance (e ~ f, a ~ b) => LiftEither (Either e a) f b where
liftEither = id
instance (a ~ b) => LiftEither (ConstRight a) e b where
liftEither (ConstRight a) = Right a
现在,您所有的示例都可以使用。比我删除的版本简单得多。