类型类中的Haskell类型解析

Key*_*nan 9 haskell type-inference

在执行类型推断时,Haskell似乎无法解析'g == [a]'.任何想法如何使这项工作?

谢谢

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)
Run Code Online (Sandbox Code Playgroud)

pig*_*ker 15

里德在他的评论中是正确的.当你写作

class Generator g where
  next :: State g a
Run Code Online (Sandbox Code Playgroud)

你真的在说

class Generator g where
  next :: forall a. State g a
Run Code Online (Sandbox Code Playgroud)

因此,从给定的状态开始g,您的客户可以生成a他们希望的任何类型的元素,而不是国家提供的任何类型g.

有三种明智的方法可以解决这个问题.我会按照我喜欢的顺序画出它们.

计划A是要认识到事物的任何生成器在某种意义上都是它们的容器,因此可以作为类型构造函数而不是类型呈现.它当然应该是a Functor并且具有高概率a 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
Run Code Online (Sandbox Code Playgroud)

如果这对您来说都是希腊语,也许现在是您在需要知道的基础上学习一些新结构的机会!

计划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)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

所有这些计划的共同点是,g和之间的功能关系在a某种程度上得到承认.没有它,没有什么可做的.