重新定义monad实例列表 [英] Redefine list monad instance

查看:86
本文介绍了重新定义monad实例列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为list monad提供我自己的实例。不幸的是,下面的代码在编译时会导致重复的实例声明错误。

  myReturn :: a  - > [a] 
myBind :: [a] - > (a - > [b]) - > [b]
实例Monad []其中
return = myReturn
(>> =)= myBind

在文档中,似乎无法在导入时隐藏实例声明,并且由于列表monad实例已在前奏中声明,所以我想我无法摆脱我认为,也许我可以至少重新绑定(>> =),然后再重新绑定 return 这样我就可以使用我自己的实现来使用do块,因为对于(>>>)应用程序,块应该只是语法糖。 =)(>>)

  let 
return = myReturn
(>> =)= myBind
in
do
item1< - list1
item2< ; - list2
return(item1,item2)

不幸的是,他们的(>> =)从其他地方,因为e它仍然使用默认列表monad实例的(>> =)



有没有使我的(>> =) return 列表monad实例的实现方法,或者至少一个使用它们的方法吗?

解决方案

您无法定义另一个 Monad 实例列表,在某些情况下,您可以定义一种新类型来解决这个问题,但是您必须手动将所有列表函数提升为新类型才能使用它们。



<要在do-blocks中使用自己的(>> =) return ,您可以使用GHC的语言扩展:

  { - #LANGUAGE NoImplicitPrelude# - } 
模块ListMon其中

import Prelude隐藏((>> =),return)

(>> =):: [a] - > (a - > [b]) - > [b]
xs>> = foo =
的案例xs [] - > [未定义]
[x] - > foo x ++ foo x
ys - >取10 $ concatMap foo $ take 5 ys

return :: a - > [a]
return x = [x,x,x]

someList :: [Int]
someList = do
k < - [1 .. 4 ]
h < - [2..3]
返回(k + 12 * h)

导致

  $ ghci ListMon 
{ - snip加载消息 - }
[ 1/1]编译ListMon(ListMon.hs,解释)
确定,加载模块:
* ListMon> someList
[25,25,25,37,37,37,26,26,26,38,38,38,27,27,27,39,39,39,28,28,28,40, 40,40]

使用 NoImplicitPrelude ,desugaring of do notation使用任何(>> =) return 在范围内。


I'd like to supply my own instance for the list monad. Unfortunately, the following causes a duplicate instance declaration error when compiling.

myReturn :: a -> [a]
myBind :: [a] -> (a -> [b]) -> [b]
instance Monad [] where
    return = myReturn
    (>>=) = myBind

From the documentation, it seems like it's not possible to hide instance declarations when importing, and since the list monad instance is already declared in the prelude, I guess I can't get rid of the import itself either.

I figured that maybe I could at least rebind (>>=) and return so that I would be able to use do blocks using my own implementation since do blocks are supposedly just syntactic sugar for applications of (>>=) and (>>).

let
    return = myReturn
    (>>=) = myBind
in
    do
        item1 <- list1
        item2 <- list2
        return (item1, item2)

Unfortunately, it seems like do blocks get their (>>=) from somewhere else, because it's still using the (>>=) of the default list monad instance.

Is there any way to make my implementations of (>>=) and return an instance of list monad, or at least a way to use them with do blocks?

解决方案

You cannot define another Monad instance for lists, in some circumstances you can define a newtype to work around that, but you'd have to manually lift all list functions to the newtype to use them.

To just use your own (>>=) and return in do-blocks, you can use a language extension with GHC:

{-# LANGUAGE NoImplicitPrelude #-}
module ListMon where

import Prelude hiding ((>>=), return)

(>>=) :: [a] -> (a -> [b]) -> [b]
xs >>= foo = case xs of
               [] -> [undefined]
               [x] -> foo x ++ foo x
               ys -> take 10 $ concatMap foo $ take 5 ys

return :: a -> [a]
return x = [x,x,x]

someList :: [Int]
someList = do
    k <- [1 .. 4]
    h <- [2 .. 3]
    return (k + 12*h)

resulting in

$ ghci ListMon
{- snip loading messages -}
[1 of 1] Compiling ListMon          ( ListMon.hs, interpreted )
Ok, modules loaded:
*ListMon> someList 
[25,25,25,37,37,37,26,26,26,38,38,38,27,27,27,39,39,39,28,28,28,40,40,40]

With NoImplicitPrelude, desugaring of do-notation uses whatever (>>=) and return are in scope.

这篇关于重新定义monad实例列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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