通用嵌套 monad 操作?
Generic nested monad manipulation?
我已经given以下class界面:
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,具有多个参数:
class Misty m => VeryMisty m a where
... banana' (Just (Just v)) = banana --?
我不确定如何在 Misty
中创建一个函数来操作这个嵌套的 monad?
我也不确定我的做法是否正确and/or最简单?
我认为您不必扩展 class,或添加子class。如果您在 banana
的签名中为 a
选择 m a
,请考虑 banana
的类型签名是什么样的(类型变量 a
可以代表任何类型,m a
):
banana :: Misty m => (m a -> m b) -> m (m a) -> m b
您是否看到这看起来已经开始非常接近 jellybean
?您只需要 "get rid" 第一个参数,并使 b
与 a
相同。实现此目的的最简单方法是使用恒等函数 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
所以你在这里看到了在这种情况下进行这种类型检查需要什么。
我已经given以下class界面:
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,具有多个参数:
class Misty m => VeryMisty m a where
... banana' (Just (Just v)) = banana --?
我不确定如何在 Misty
中创建一个函数来操作这个嵌套的 monad?
我也不确定我的做法是否正确and/or最简单?
我认为您不必扩展 class,或添加子class。如果您在 banana
的签名中为 a
选择 m a
,请考虑 banana
的类型签名是什么样的(类型变量 a
可以代表任何类型,m a
):
banana :: Misty m => (m a -> m b) -> m (m a) -> m b
您是否看到这看起来已经开始非常接近 jellybean
?您只需要 "get rid" 第一个参数,并使 b
与 a
相同。实现此目的的最简单方法是使用恒等函数 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
所以你在这里看到了在这种情况下进行这种类型检查需要什么。