Haskell在执行类型推断时似乎无法解析'g == [a]'。任何想法如何使这项工作?
THX
module X where
import Control.Monad.State.Lazy
class Generator g where
next :: State g a
instance Generator ([] a) where
next = nextL
nextL :: State [a] a
nextL = state $ split
split :: [a] -> (a, [a])
split l = (head l, tail l)
答案 0 :(得分:15)
里德在评论中说得对。当你写
class Generator g where
next :: State g a
你真的在说
class Generator g where
next :: forall a. State g a
因此,从g
中的给定状态,您的客户端可以生成他们希望的任何类型a
的元素,而不是g
中状态提供的任何类型
有三种明智的方法可以解决这个问题。我会按照我喜欢的顺序画出它们。
计划A是要认识到事物的任何生成器在某种意义上都是它们的容器,因此可以作为类型构造函数而不是类型呈现。它当然应该是Functor
并且概率很高Comonad
。所以
class Comonad f => Generator f where
move :: forall x. f x -> f x
next :: forall x. State (f x) x
next = state $ \ g -> (extract g, move g)
-- laws
-- move . duplicate = duplicate . move
instance Generator [] where
move = tail
如果这对您来说都是希腊语,也许现在您有机会在需要知道的基础上学习一些新的结构!
计划B是忽略comonadic结构并添加关联类型。
class Generator g where
type From g
next :: State g (From g)
instance Generator [a] where
type From [a] = a
next = state $ \ (a : as) -> (a, as)
Plan C是“功能依赖”版本,与Cirdec建议的MonadSupply相似。
class Generator g a | g -> a where
next :: State g a
instance Generator [a] a where
next = state $ \ (a : as) -> (a, as)
所有这些计划的共同之处在于g
和a
之间的功能关系在某种程度上得到了承认。没有它,没有什么可做的。