通用嵌套monad操作?

时间:2017-02-06 10:33:46

标签: haskell monads

我一直是given以下的类接口:

class Misty m where
  banana :: (a -> m b) -> m a -> m b
  unicorn :: a -> m a

现在我需要修改它以启用:

jellybean :: (Misty m) => m (m a) -> m a

我认为这个问题迫使我要添加一个Misty的子类,其中包含多个参数:

class Misty m => VeryMisty m a where
  ... banana' (Just (Just v)) = banana --? 

我不确定如何在Misty中创建一个函数来操作这个嵌套的monad?

我也不确定我的方法是否正确和/或最简单?

1 个答案:

答案 0 :(得分:5)

我认为你不必扩展类,或者添加子类。如果您要在banana的签名中为m a选择a,请考虑banana的类型签名是什么(类型变量a可以代表任何类型,也适用于m a):

banana :: Misty m => (m a -> m b) -> m (m a) -> m b

你是否看到这已经开始看起来非常接近jellybean了?您只需要“摆脱”第一个参数,并使ba相同。实现此目标的最简单方法是使用标识函数id

jellybean :: (Misty m) => m (m a) -> m a
jellybean x = banana id x

更容易看到第二步的好方法是,一旦发现可以使用jellybean的第一个参数,因为banana的第二个参数是使用类型的洞

jellybean :: (Misty m) => m (m a) -> m a
jellybean x = banana _ x

在将其加载到REPL中时,Haskell将打印出来:

 Found hole `_' with type: m a -> m a

所以你在这里看到了你需要做什么才能做出这个类型检查。