【发布时间】:2013-04-06 22:31:14
【问题描述】:
我正在研究 HList 实现,但我一直在尝试为其实现 map 函数。我尝试了很多不同的方法,但每一种我都会遇到与该函数相关的编译器错误。
以下是我想如何使用通用函数Just 将其应用于输入数据结构的所有元素的示例。
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
-- | An input heterogenous data structure
recursivePairs :: (Int, (Char, (Bool, ())))
recursivePairs = (1, ('a', (True, ())))
-- | This is how I want to use it
recursivePairs' :: (Maybe Int, (Maybe Char, (Maybe Bool, ())))
recursivePairs' = hMap Just recursivePairs
class HMap f input output where
hMap :: f -> input -> output
-- | A counterpart of a Nil pattern match for a list
instance HMap f () () where
hMap _ _ = ()
-- | A counterpart of a Cons pattern match for a list
instance
( HMap f iTail oTail,
Apply f iHead oHead ) =>
HMap f (iHead, iTail) (oHead, oTail)
where
hMap f (head, tail) = (apply f head, hMap f tail)
class Apply f input output where
apply :: f -> input -> output
instance Apply (input -> output) input output where
apply = id
这样我得到以下编译器错误:
No instance for (Apply (a0 -> Maybe a0) Int (Maybe Int))
arising from a use of `hMap'
The type variable `a0' is ambiguous
有没有办法解决这个问题,如果没有,为什么?
【问题讨论】:
-
我认为问题在于类型系统没有意识到您在每个连续的应用程序上使用不同的具体类型实例化
Just,因为您对hMap的定义不断重复使用相同的f.第一次应用类型为Int -> Maybe Int,第二次应用类型为Char -> Maybe Char。但是,我仍然不太确定如何解决它。 -
@GabrielGonzalez 是的,这正是问题所在。如果您将fundep
| input output -> f添加到Apply类,错误消息会说它正在寻找实例,例如(Bool -> Maybe Bool) Char (Maybe Char)。我正在考虑使用cast来断开f在类型级别上的两种用法,但这感觉不太自然,并且依赖Typeable也不是很吸引人。