来自Haskell新手的简短版本:假设我有一个Container,其中Container有* -> *
种。我想把它放到另一个容器中,仍然使第二个容器成为原始类的一个实例,如:
data Container2 a container = Container2 (container a)
instance Container (Conrainer2 a) where ...
但似乎这是不可能的,因为GHC总会产生如下错误:
Kind mis-match
The first argument of `Container' should have kind `* -> *',
but `Container2 a' has kind `(* -> *) -> *'
可以解决这个问题吗?
长版本:我正在使用以下代码来编写Java中的迭代器接口:
module Main where
data NextResult a iter = Stop | More a (iter a)
class Iter iter where
next :: iter a -> NextResult a iter
-- Convert iterator to a list
toList :: (Iter c) => c a -> [a]
toList iter = case next iter of
Stop -> []
More value iter2 -> value : toList iter2
-- List itself is iterator
instance Iter [] where
next [] = Stop
next (x:xs) = More x xs
main = let iter = [1,2,3,4,5] in print $ toList iter
使用GHC 7.4.1,这将编译并打印预期的1 2 3 4 5
。现在我想定义一个转换迭代器,它从函数和迭代器构造一个新的迭代器。为此,我添加了以下几行:
data TransformedIter from to iter = TransformedIter (from->to) (iter from)
instance Iter (TransformedIter from to) where
next (TransformedIter f iter) = case next iter of
Stop -> Stop
More value iter2 -> More (f value) (TransformedIter f iter2)
但是这产生了错误:
Main.hs:21:16:
Kind mis-match
The first argument of `Iter' should have kind `* -> *',
but `TransformedIter from to' has kind `(* -> *) -> *'
In the instance declaration for `Iter (TransformedIter from to)'
我试图解决这个问题,但结果始终是一种或另一种类型的错误。那么如何在Haskell中建模这样的转换呢?
我误解了实例声明是如何工作的。基于下面的建议,我翻了TransformedIter类型的顺序,结果是:
module Main where
data NextResult a iter = Stop | More a (iter a)
class Iter iter where
next :: iter a -> NextResult a iter
toList :: (Iter c) => c a -> [a]
toList iter = case next iter of
Stop -> []
More value iter2 -> value : toList iter2
instance Iter [] where
next [] = Stop
next (x:xs) = More x xs
main = let iter = [1,2,3,4,5] in print $ toList iter
data TransformedIter iter from to = TransformedIter (from->to) (iter from)
instance Iter (TransformedIter iter from) where
next (TransformedIter f iter) = case next iter of
Stop -> Stop
More value iter2 -> More (f value) (TransformedIter f iter2)
然而,这产生了另一个错误:
Main.hs:22:40:
No instance for (Iter iter)
arising from a use of `next'
In the expression: next iter
In the expression:
case next iter of {
Stop -> Stop
More value iter2 -> More (f value) (TransformedIter f iter2) }
In an equation for `next':
next (TransformedIter f iter)
= case next iter of {
Stop -> Stop
More value iter2 -> More (f value) (TransformedIter f iter2) }
我将实例声明更改为:
instance Iter (Iter iter => TransformedIter iter from) where
那产生了另一个错误:
Main.hs:21:10:
Illegal instance declaration for `Iter
(Iter iter => TransformedIter iter from)'
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Iter (Iter iter =>
TransformedIter iter from)'
在我添加-XFlexibleInstances之后我得到了:
Main.hs:21:10:
Illegal polymorphic or qualified type:
Iter iter => TransformedIter iter from
In the instance declaration for `Iter (Iter iter =>
TransformedIter iter from)'
所以我仍然没有看到如何声明TransformedIter是Iter的一个实例。有线索吗?
使用GADT GHC扩展我设法定义了TransformedIter:
module Main where
data NextResult a iter = Stop | More a (iter a)
class Iter iter where
next :: iter a -> NextResult a iter
toList :: (Iter c) => c a -> [a]
toList iter = case next iter of
Stop -> []
More value iter2 -> value : toList iter2
instance Iter [] where
next [] = Stop
next (x:xs) = More x xs
data TransformedIter iter from to where
TransformedIter :: Iter iter =>
(from->to) -> (iter from) -> TransformedIter iter from to
instance Iter (TransformedIter iter from) where
next (TransformedIter f iter) = case next iter of
Stop -> Stop
More value iter2 -> More (f value) (TransformedIter f iter2)
twice = (*) 2
main = let iter = TransformedIter twice [1,2,3,4,5] in print $ toList iter
编译并打印预期的2 4 6 8 10.但这个扩展是否真的有必要?
答案 0 :(得分:1)
答案在J. Abrahamson的评论中给出,现在我终于有一个版本无需使用任何GHC扩展(我之前在实例声明中使用了错误的语法):
module Main where
data NextResult a iter = Stop | More a (iter a)
class Iter iter where
next :: iter a -> NextResult a iter
toList :: (Iter c) => c a -> [a]
toList iter = case next iter of
Stop -> []
More value iter2 -> value : toList iter2
instance Iter [] where
next [] = Stop
next (x:xs) = More x xs
data TransformedIter iter from to = TransformedIter (from->to) (iter from)
instance Iter iter => Iter (TransformedIter iter from) where
next (TransformedIter f iter) = case next iter of
Stop -> Stop
More value iter2 -> More (f value) (TransformedIter f iter2)
twice = (*) 2
main = let iter = TransformedIter twice [1,2,3,4,5] in print $ toList iter
打印2 4 6 8 10