gpt4 book ai didi

haskell - 重新定义列表 monad 实例

转载 作者:行者123 更新时间:2023-12-02 12:13:20 26 4
gpt4 key购买 nike

我想为列表单子(monad)提供我自己的实例。不幸的是,以下内容会在编译时导致重复实例声明错误。

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

从文档来看,导入时似乎不可能隐藏实例声明,并且由于列表 monad 实例已经在前奏中声明,我想我也无法摆脱导入本身。

我想也许我至少可以重新绑定(bind) (>>=)return 这样我就可以使用我自己的实现来使用 do block ,因为 do block 据说只是 (>>=)(>>) 应用程序的语法糖。

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

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

有没有办法让我的 (>>=) 实现和 return 列表 monad 的实例,或者至少有一种将它们与 do block 一起使用的方法?

最佳答案

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

要在 do block 中使用您自己的 (>>=)return,您可以使用 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)

结果

$ 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]

使用 NoImplicitPrelude,do 表示法的脱糖使用范围内的任何 (>>=)return

关于haskell - 重新定义列表 monad 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11605027/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com