gpt4 book ai didi

javascript - 单子(monad)组合练习错误

转载 作者:行者123 更新时间:2023-12-01 02:02:41 28 4
gpt4 key购买 nike

背景

我正在阅读《大多数》Adequate Guide to Functional Programming并进行所有练习。我正在阅读第 9 章,Monadic Onions,但我在练习中遇到了困难。

练习 1

Considering a User object as follow, use safeProp and map/join or chain to safely get the street name when given a user:

// safeProp :: String -> Object -> Maybe a
const safeProp = curry((p, obj) => compose(Maybe.of, prop(p))(obj));

const user = {
id: 1,
name: 'Albert',
address: {
street: {
number: 22,
name: 'Walnut St',
},
},
};

解决方案1

// getStreetName :: User -> Maybe String
const getStreetName = compose(
chain( safeProp( "name" ) ),
chain( safeProp( "street" ) ),
safeProp( "address" )
);

这个很简单。 safeProp 返回一个 Maybe Monad。因此,在编写 safeProp 时,我们需要使用 chain (又名 flatMap )来跟进,否则就不会得到一个 Maybe。 of("value") 我们最终会得到 Maybe.of( Maybe.of("value") )

规则推断:如果你想组合函数A和函数B,并且都返回Monad,请使用chain!

练习 2

Given the following functions, use getFile to get the filepath, remove the directory and keep only the basename, then purely log it. Hint: you may want to use split and last to obtain the basename from a filepath.

// getFile :: () -> IO String
const getFile = () => IO.of('/home/mostly-adequate/ch9.md');

// pureLog :: String -> IO ()
const pureLog = str => new IO(() => console.log(str));

解决方案2

const getBaseName = compose( last, split("/") );

const logFilename = compose(
chain( pureLog ),
map( getBaseName ),
getFile
);

这个有点棘手,但我也成功了。

因此,getFile 返回一个 IO Monad。但是 getBaseMap 仅返回一个字符串。因此,我有返回 Monad 的函数 A 和返回原始类型的函数 B。我无法使用 chain 组合它们,因为函数 B 没有任何需要展平的内容。这意味着我需要 map 来组合 A 和 B!

又一条规则!

现在,我需要将 B 与 pureLog ( C ) 组合起来。在 B 上应用映射后,它将返回带有转换值的 IO Monad。我们称其为MB。鉴于我需要用 C(返回一个 monad)组成 MB,我可以应用规则 1 并简单地使用 chain

唷!

我们来看最后一篇!

练习 3:

Given the following functions, use validateEmail, addToMailingList and emailBlast to create a function which adds a new email to the mailing list if valid, and then notify the whole list.

// validateEmail :: Email -> Either String Email // addToMailingList :: Email -> IO([Email]) // emailBlast :: [Email] -> IO ()

解决方案 3?

我不知道如何制作这个......

这是我到目前为止所做的:

// joinMailingList :: Email -> Either String (IO ())
const joinMailingList = compose(
chain( emailBlast ),
chain( addToMailingList ),
validateEmail
);

但这是错误的。我收到以下错误:

The function has an invalid type; hint: joinMailingList should return an Either String (IO ())

问题:

  1. 我该如何解决这个问题?有人可以解释一下我出了什么问题吗?
  2. 我是否应该从之前的练习中推断出额外的规则(我是否在这里遗漏了一些可组合性规则)?

最佳答案

// validateEmail :: Email -> Either String Email
// addToMailingList :: Email -> IO([Email])
// emailBlast :: [Email] -> IO ()

意味着您不能使用Either.chain,您必须映射Either String组合中的第一个函数 (validateEmail) 返回。如您所知,“我无法使用链来组合它们,因为函数 B 没有任何需要展平的内容。”。

还请注意,我们这里有两个单子(monad),两个不同单子(monad):EitherIOchain 不适用于任何 monad,它仅适用于其两个参数中相同 monadic 类型。每个 monad(即每个类型的 monad)都有自己的 chain 方法。使用单个链函数只是一种抽象,它利用运行时多态性(或者编译时多态性,如果该语言有支持它的编译器)。所以我们需要

function joinMailingList(email) {
return Either.map(validateEmail(email), addAndBlast)
}
function addAndBlast(email) {
return IO.chain(addToMailingList(email), emailBlast)
}

关于javascript - 单子(monad)组合练习错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50423756/

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