我正在阅读大部分Adequate Guide to Functional Programming并进行所有练习。我在第9章 Monadic Onions 但我正在努力练习。
考虑如下的用户对象,在给定用户时,使用
safeProp
和map/join
或chain
安全地获取街道名称:// 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', }, }, };
// 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,并且都返回Monads,请使用chain
!
给定以下函数,使用getFile获取文件路径,删除目录并仅保留基本名称,然后纯粹记录它。提示:您可能希望使用
split
和last
从文件路径中获取基本名称。// getFile :: () -> IO String const getFile = () => IO.of('/home/mostly-adequate/ch9.md'); // pureLog :: String -> IO () const pureLog = str => new IO(() => console.log(str));
const getBaseName = compose( last, split("/") );
const logFilename = compose(
chain( pureLog ),
map( getBaseName ),
getFile
);
这个有点棘手,但我也管理过它。
因此,getFile
返回IO Monad。但是getBaseMap
只返回一个字符串。
所以,我有函数A返回一个Monad,函数B返回一个基本类型。我无法使用chain
撰写它们,因为函数B没有任何需要展平的东西。这意味着我需要map
用B组成A!
又一条规则!
现在,我需要用pureLog(C)编写B.
在B上的apllying map之后,它将返回具有转换值的IO Monad。让我们称之为MB。鉴于我需要使用C(返回monad)来编写MB,我可以应用规则1并只使用chain
。
P!
让我们去最后一个!
鉴于以下功能,使用
validateEmail
,addToMailingList
和emailBlast
创建一个功能,如果有效,则会向邮件列表添加新电子邮件,然后通知整个列表。< / p>// validateEmail :: Email - &gt;字符串电子邮件 // addToMailingList :: Email - &gt; IO([电子邮件]) // emailBlast :: [电子邮件] - &gt; IO()
我不知道如何制作这个....
这是我到目前为止所做的:
// joinMailingList :: Email -> Either String (IO ())
const joinMailingList = compose(
chain( emailBlast ),
chain( addToMailingList ),
validateEmail
);
但这是错误的。我得到了以下错误:
该函数的类型无效;提示:
joinMailingList
应该返回一个字符串(IO())
问题:
答案 0 :(得分:2)
// validateEmail :: Email -> Either String Email // addToMailingList :: Email -> IO([Email]) // emailBlast :: [Email] -> IO ()
表示您无法使用Either.chain
,您必须<{> 1}} 超过作品中第一个函数的map
Either String
})返回。如您所知,“我不能使用链来组合它们,因为函数B没有任何东西需要展平。”。
另请注意,我们这里有两个 monad,两个不同的 monad:validateEmail
和Either
。 IO
不适用于任何 monad,它只适用于其两个参数中的相同的 monadic类型。每个monad(即每个monad类型)都有自己的chain
方法。使用单个chain
函数只是一个抽象,它利用运行时多态性(或编译时多态性,如果语言有编译器支持)。所以我们需要
chain