Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.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_Functor - Fatal编程技术网

在Haskell中从头定义monad

在Haskell中从头定义monad,haskell,monads,functor,Haskell,Monads,Functor,在研究了Haskell中的单子之后——这是一个非常吸引人的主题——我想知道我是否可以自己定义一个单子,而不用使用已经定义好的类型类 我不想让Monad成为Functor的一个实例,我只想定义一个Monad本身,它有自己的fmap函数(我还想更改一些函数名,比如return并将其称为unit) monad可以由bind操作符(>>=)和函数return定义,但也可以根据return和join定义,因为最后一个函数可以用bind操作符来表示:join m=m>=id。因此,monad(从技术上)可以

在研究了Haskell中的单子之后——这是一个非常吸引人的主题——我想知道我是否可以自己定义一个单子,而不用使用已经定义好的类型类

我不想让
Monad
成为
Functor
的一个实例,我只想定义一个Monad本身,它有自己的
fmap
函数(我还想更改一些函数名,比如
return
并将其称为
unit

monad可以由bind操作符
(>>=)
和函数
return
定义,但也可以根据
return
join
定义,因为最后一个函数可以用bind操作符来表示:
join m=m>=id
。因此,monad(从技术上)可以定义为
return
join
等。函数
fmap
是必需的(也是Haskell中存在
Functor
的基础),但也可以用
return
来定义,因为它也可以(我认为)定义如下:
fmap f m=m>=return。f
(在编写编辑之前,
fmap f m=return.f
;这显然是一个打字错误)

但我知道这不如使用预定义的
Monad
typeclass有效,只是为了更好地理解Haskell语言

我怎样才能做到这一点?这是我脑海中对这个概念的描述,现在,它不是有用的代码:

——只是一个草图
infixr 9∘
(∘) :: (b->c)->(a->b)->a->c
(∘) g f x=g(f x)
--(f)∘ g) x=f(gx)
--我自己的“fmap”
--映射器id=id
--制图员(f∘ g) =映射器f∘ 映射器g
--我的单子
类MyMonadBase(m::*->*),其中
单位::a->m a--退货
join::m(MA)->m a
join=(>>=id)
映射器f m=m>>=单位∘ F
--测试:
数据树a=叶a |分支(树a)(树a)
实例MyMonadBase树,其中
单位=叶
连接(叶x)=x
连接(分支l r)=分支(连接l)(连接r)

我是否在正确的轨道上(概念上)?

一些小的修正:

monad可以由bind操作符
(>>=)
和函数
return
定义,但也可以根据
return
join
定义,因为最后一个函数可以用bind操作符来表示:
join m=m>=id

结论(“[a monad]也可以用
返回
连接
”来定义)是正确的,但前提是(“因为[
连接
]可以用绑定运算符来表示”)这并不意味着它。相反,您必须表明您要忽略的运算符--bind运算符--可能是根据您拥有的内容定义的--
return
join
。一旦您尝试这样做,您就会明白为什么单子也是一个函子是如此重要:

m >>= f = join (fmap f m)
函数
fmap
是必需的(也是Haskell中存在
Functor
的基础),但也可以定义为
return
,因为它也可以(我认为)定义如下:
fmap f m=return.f

这不是对
fmap
的正确定义,你应该怀疑,因为右边没有提到
m
!正确的版本应该是:

fmap f m = m >>= return . f
但是现在这是一个循环定义,因为上面我们计划用
fmap
来定义
(>>=)
。所以如果您想让
返回
加入
Monad
的基本操作,您确实需要单独实现
fmap

我知道这不如使用预定义的
Monad
typeclass有效

我看不出有任何理由先验地相信这一点。之所以选择
(>>=)
而不是
join
,不是因为它更高效,而是因为在编程中使用单子时,这是一种自然的操作

至于您的实际代码,我认为它看起来不错,但有两个警告:

  • 我强烈怀疑您对
    mapper
    的定义与您认为的不一样。在
    mapper id=id
    行中,左侧的模式
    id
    匹配所有传入值,右侧的变量
    id
    返回的值不变。行
    mapper(f∘ g) =映射器f∘ mapper g
    是无效的Haskell。(也许这两行是用来记录mapper
  • 所需的法律,而不是实际的代码?)

  • (>>=)
    而言,提供
    join
    mapper
    的默认实现是很奇怪的——这两种实现都是出于上述原因(所有三种都是基本的,必须定义),并且因为
    (>>=)
    不是类操作,因此用户无法以有意义的方式定义


  • 一些小的修正:

    monad可以由bind操作符
    (>>=)
    和函数
    return
    定义,但也可以根据
    return
    join
    定义,因为最后一个函数可以用bind操作符来表示:
    join m=m>=id

    结论(“[a monad]也可以用
    返回
    连接
    ”来定义)是正确的,但前提是(“因为[
    连接
    ]可以用绑定运算符来表示”)这并不意味着它。相反,您必须表明您要忽略的运算符--bind运算符--可能是根据您拥有的内容定义的--
    return
    join
    。一旦您尝试这样做,您就会明白为什么单子也是一个函子是如此重要:

    m >>= f = join (fmap f m)
    
    函数
    fmap
    是必需的(也是Haskell中存在
    Functor
    的基础),但也可以根据
    返回定义,因为它可能