Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 当泛型类型不是monad时?_Haskell_Monads - Fatal编程技术网

Haskell 当泛型类型不是monad时?

Haskell 当泛型类型不是monad时?,haskell,monads,Haskell,Monads,Haskell允许围绕另一个类型定义新类型,从而创建 . 因此,可以在以下情况下区分(Int,Int) 数据时间=时间(Int,Int)--(h:m)和数据坐标=坐标(Int,Int)--(x,y)。 这些新类型将具有相关函数,知道包装的“base”类型实际上是Int 进一步的一步是创建“泛型”类型,方法是使用data子句中的“类型参数”,如著名的monad:data-Maybe t=Nothing | Just t。 这类泛型类型将被广泛的函数和 寻址,即:异常:可能,全局状态:状态,输入/输

Haskell允许围绕另一个类型定义新类型,从而创建 . 因此,可以在以下情况下区分
(Int,Int)
数据时间=时间(Int,Int)
--(h:m)和
数据坐标=坐标(Int,Int)
--(x,y)。 这些新类型将具有相关函数,知道包装的“base”类型实际上是
Int

进一步的一步是创建“泛型”类型,方法是使用
data
子句中的“类型参数”,如著名的monad:
data-Maybe t=Nothing | Just t
。 这类泛型类型将被广泛的函数和 寻址,即:异常:可能,全局状态:状态,输入/输出:IO,不确定性:[],环境:读取器,记录器:写入器。 这里出现了具有两个函数的便利性:
return::a->ma
用于围绕类型
a
构建上下文,以及
(>>=)::ma->(a->mb)->mb
用于基于先前的
a->mb
自动具有函数
ma->mb
。monad类对此进行了总结:

class Monad m where
        return :: a -> m a
        (>>=)  :: m a -> (a -> m b) -> m b
因此,新的泛型类型必须定义
return
>=
的含义,以便它们成为
Monad
的实例

在我看来,每种泛型类型都会出现这种情况,因此具体问题如下:

  • 每个泛型类型
    数据神话t=…
    都必须是Monad的实例
  • 至少在一般情况下,每个泛型类型
    数据神话t=…
    都是Monad的实例,这样方便吗
  • 在任何情况下,泛型类型
    数据神话t=…
    都不能是Monad的实例吗? (除了琐碎的案件)。为什么?
  • 即使是一个具体的上下文类型,
    datatime=Time(Int,Int)
    ,也是Monad,这有意思吗
  • 欢迎并希望对上述解释进行示例、更正和编辑


    谢谢。

    参数化类型的概念比只有一个参数的类型的特例更一般,而这些参数的行为恰好与monad类似

    所以,不,不是所有种类
    (*->*)
    的类型都必须是单子,这也不方便

    例如:

    data HomogenousTriple a = T a a a
    
    为什么以及如何成为单子?

    要给出一个完全不是单子的例子,请考虑

    data Shower a = Shower (a -> String)
    
    这与函子有点相反(实际上是对偶的):a

    将此与

    fmap f (Identity x)  = Identity (f $ x)
    
    逆变函子不能是(非平凡的)单子,也不能是类似物。要知道为什么,你需要考虑什么是:它是一种内括约肌的幺半群。它必须是endo,因为关键的操作
    join::m(ma)->ma
    意味着应用
    m
    两次会使您处于同一类别。例如,如果您要将
    fmap
    a功能
    a->B
    覆盖到任意一侧,您将沿着相同的方向:

    fmap f        :: m A     -> m B
    fmap (fmap f) :: m (m A) -> m (m B)
    
    (这同样适用于,它们也是(协变的,而不是逆变的)函子。在这里,操作是
    duplicate::w a->w(w a)
    ,它反过来,但仍然必须保持在同一类别中。)

    对于逆变函子,这不起作用!原因是,

    contramap f             :: q B     -> q A
    contramap (contramap f) :: q (q A) -> q (q B)
    
    i、 如果你迭代函子,它会在反变和协变之间切换。因此,它不能形成任何像幺半群结构这样的东西。

    这里有些东西不是单子,它甚至不是一个
    函子

    -- from Data.Monoid
    newtype Endo a = Endo { appEndo :: a -> a }
    
    特别是,
    Endo
    的类型参数
    a
    同时显示在逆变和协变位置---这种类型不能是
    函子
    逆变
    函子---它必须同时是这两种类型

    当然,如果你只是稍微概括一下,你就会得到
    阅读器
    单子

    newtype Reader r a = Reader { runReader :: r -> a }
    
    因为我们现在已经分离出类型参数的用法,一个是协变的,一个是逆变的


    已经证明了
    Endo
    不能是
    函子
    逆变
    ,因为它必须同时是这两种类型,是否存在同时是这两种类型的数据类型?有一个简单的技巧论证表明(1)存在,并且(2)它们总是使用幻象参数

    我们将使用空数据类型(void
    包提供了一种空数据类型,但很容易重新实现)。空数据类型的有趣之处在于,可以使用空数据类型生成
    荒谬的
    ,该函数接受一个不可能的参数并返回任何内容

    data Void = Void Void     -- there are no values of Void 
                              -- ... unless there are values of Void
    
    absurd :: Void -> a
    absurd (Void v) = absurd v
    
    然后,结合
    函子
    逆变
    给我们提供了一个非常有趣的函数

    contramap absurd :: Contravariant f => f a    -> f Void
    fmap      absurd :: Functor       f => f Void -> f a
    
    fmap absurd . contramap absurd 
      :: (Contravariant f, Functor f) => f a -> f b
    
    换句话说,它允许我们编写一种基于函子的
    强制
    ,如果
    f
    实际上包含
    a
    类型的任何值,这是不可能的,因此我们知道这样的
    f
    必须使用
    a
    作为幻象参数

    data Constant b a = Constant { runConstant :: b }
    
    coerceConstant :: Constant a -> Constant b
    coerceConstant = Constant . runConstant
    
    instance Functor (Constant b) where
      fmap _ = coerceConstant
    
    instance Contravariant (Constant b) where
      contramap _ = coerceConstant
    
    这甚至为我们提供了一种实现非常无聊的
    Monad

    instance Monoid b => Monad (Constant b) where
      return _ = Constant mempty
      c >>= _ = coerceConstant c
    

    仅针对具有一个参数的类型:您会提供一个链接还是它的一个示例(不是monad的类型)?Thx.实际上这是一个单子。它同构于一个有三个元素的类型上的读卡器单子!如果Ingo声称不能给
    数据同源性指令a=ta a
    一个monad实例,那么这个说法是错误的。@托梅利斯我不是这样说的-我声称a)一个人通常不需要它,b)甚至不是为了方便。或者,重复我自己的话:出于什么原因,我们应该为它创建一个Monad实例?
    bind
    For
    HomogeneousTriple
    对应于组件操作
    do x啊是的,对于这样的问题,一个强制性的参考当然是,它详细讨论了
    函子
    单子
    等的层次结构。@Ingo和leftaroundabout:很明显,你们两个提供了明显的答案,其中类型有一个参数,但有两个或更多的参数值不适合(直截了当地说)s
    instance Monoid b => Monad (Constant b) where
      return _ = Constant mempty
      c >>= _ = coerceConstant c