广义新类型派生 [英] Generalized Newtype Deriving

查看:105
本文介绍了广义新类型派生的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Haskell可以在下面的T1中派生MonadState s的实例,但不能在T2中派生该实例,这是非常相似的类型.我应该以哪种方式修改T2的代码,以便可以自动派生MonadState s的实例?

Haskell can derive the instance for MonadState s in T1 below but not in T2 which is however a very similar type. In which way should I modify the code for T2 so that the instance for MonadState s can be automatically derived?

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import Control.Monad.Reader
import Control.Monad.State

newtype T1 r s a = 
  T1 { runT1 :: ReaderT r (State s) a }
  deriving (Monad, MonadReader r, MonadState s)

newtype T2 r s a = 
  T2 { runT2 :: StateT r (State s) a }
  deriving (Monad, MonadState r, MonadState s)

推荐答案

对于类型为MonadState的类型,您不能具有两个实例.这是因为MonadState被定义为

You can't have a type have two instances for MonadState. This is because MonadState is defined as

class Monad m => MonadState s m | m -> s where
    get :: m s
    set :: s -> m ()
    state :: (s -> (a, s)) -> m a

关键部分是| m -> s.这需要扩展名FunctionalDependencies,并指出对于任何m,我们都会自动知道关联的s.这意味着对于任何给定的ms只能有一个选项有效.因此,除非r ~ s,否则您不能同时在MonadState r mMonadState s m上使用它.如果是r ~ s,那么编译器将如何知道将其应用于哪个基础monad?在这种情况下,我认为您还会发现,如果创建具有后缀以指示哪个功能的getput函数,例如getInnergetOutersetOuter.

The key part is the | m -> s. This requires the extension FunctionalDependencies, and states that for any m, we automatically know the associated s. This means that for any given m, there can only be one choice for s that is valid. So you can't have it work for both MonadState r m and MonadState s m unless r ~ s. If r ~ s, then how would the compiler know which underlying monad for it to apply to? In this case, I think you'll also find that it'll be much easier to understand and work with the code if you create get and put functions that have suffixes to indicate which, like getInner, setInner and getOuter, setOuter.

这篇关于广义新类型派生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆