Monadic作曲练习错误

时间:2018-05-19 09:27:19

标签: javascript functional-programming monads chain

背景

我正在阅读大部分Adequate Guide to Functional Programming并进行所有练习。我在第9章 Monadic Onions 但我正在努力练习。

练习1

  

考虑如下的用户对象,在给定用户时,使用safePropmap/joinchain安全地获取街道名称:

// 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,并且都返回Monads,请使用chain

练习2

  

给定以下函数,使用getFile获取文件路径,删除目录并仅保留基本名称,然后纯粹记录它。提示:您可能希望使用splitlast从文件路径中获取基本名称。

// 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只返回一个字符串。 所以,我有函数A返回一个Monad,函数B返回一个基本类型。我无法使用chain撰写它们,因为函数B没有任何需要展平的东西。这意味着我需要map用B组成A!

又一条规则!

现在,我需要用pureLog(C)编写B. 在B上的apllying map之后,它将返回具有转换值的IO Monad。让我们称之为MB。鉴于我需要使用C(返回monad)来编写MB,我可以应用规则1并只使用chain

P!

让我们去最后一个!

练习3:

  

鉴于以下功能,使用validateEmailaddToMailingListemailBlast创建一个功能,如果有效,则会向邮件列表添加新电子邮件,然后通知整个列表。< / p>      

// validateEmail :: Email - &gt;字符串电子邮件   // addToMailingList :: Email - &gt; IO([电子邮件])   // emailBlast :: [电子邮件] - &gt; IO()

解决方案3?

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

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

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

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

  

该函数的类型无效;提示:joinMailingList应该返回一个字符串(IO())

问题:

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

1 个答案:

答案 0 :(得分:2)

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

表示您无法使用Either.chain,您必须<{> 1}} 超过作品中第一个函数的map Either String })返回。如您所知,“我不能使用链来组合它们,因为函数B没有任何东西需要展平。”。

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

chain
相关问题