【问题标题】:How to define `bind` for a type with record syntax in Haskell?如何在 Haskell 中为具有记录语法的类型定义`bind`?
【发布时间】:2020-01-05 13:29:05
【问题描述】:

在解决 Haskell 课程中的 Monad 作业时,我完全陷入困境。有一个示例数据类型,我想为其定义特定于 Monad 的函数:

data MyMonad a = MyMonad { func :: String -> a }

instance Functor MyMonad where
    fmap f (MyMonad x) = MyMonad (\a -> f (x a))   

instance Applicative MyMonad where
    pure x = MyMonad (\a -> x)
    (MyMonad f) <*> (MyMonad g) = MyMonad (\a -> (f a)(g a))

instance Monad MyMonad where
    return x = MyMonad (\a -> x)
    MyMonad x >>= f = f (\a -> x a) --my wrong definition 

一旦声明了 Functor 和 Applicative 实例,我会尝试对 Monad 做同样的事情,但是......我并没有更接近于理解如何将记录语法 func 放入 f 函数中.到目前为止,我认为bind 是一个函数,可以在将MyMonad 映射到f 之前获取x。这只是任何 Monad 的一个关键特性——能够将一些值从一种数据类型上下文放到另一个数据类型上下文中——据我所知。老实说,我知道 bind 在 Monad 实例中对 [a], Maybe 和其他几个永远存在的类型的定义。是的,我清楚地看到 Monad 类的共同目的是什么。但是,我需要在这种特定情况下获得任何建议,以增强我对处理记录之类的方式的理解。

【问题讨论】:

    标签: haskell functional-programming monads


    【解决方案1】:

    MyMonad x 中的x 具有String -&gt; a 类型,而f 具有a -&gt; MyMonad b 类型,因此我们应该返回一个MyMonad b(它包装了一个函数String -&gt; b)

    因此,我们应该构造一个将s :: String 映射到b 的函数。我们可以通过首先将s 传递给x 函数并检索a 类型的值来做到这一点。接下来,我们可以使用a 作为该参数调用f,并检索MyMonad g。然后我们可以将s 应用到g

    因此,我们可以将Monad 实例实现为:

    instance Monad MyMonad where
        return x = MyMonad (\a -> x)
        MyMonad x >>= f = MyMonad (\s -> let MyMonad g = f (x s) in g s)

    由于您定义了“getter”func :: MyMonad a -&gt; a -&gt; String,我们可以使用该 getter 而不是使用 let … in … 表达式来“解包”MyMonad 数据构造函数中的值:

    instance Monad MyMonad where
        return x = MyMonad (\a -> x)
        MyMonad x >>= f = MyMonad (\s -> func (f (x s)) s)

    【讨论】:

    • 我试图将&gt;&gt;= 类型定义映射到这个真实案例中,但是(正如我在你的回答之后知道的那样)我非常非常远......积极地,现在它很清楚,包括一些让我感到奇怪的特殊性。非常有帮助,非常感谢。
    猜你喜欢
    • 2010-12-26
    • 2021-09-08
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多