npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

fm-markstien

v1.0.7

Published

函数式容器库

Readme

Functor and Monad

一个小例子

它是什么?

这是一个封装了几个基本的函数式容器的库。

  1. 使用本库,必须了解JavaScript的函数式编程范式
  2. 使用本库,必须了解函数式编程的functor与monand等概念。

如何使用?

npm install --save fm-markstien

导入变量:

const{fm}=require("fm-markstien/use");
const {Container, Maybe, Left, Right, IO, untils}=fm;

文档:

声明:笔者把存放值的概念(比如态射)统统称为容器(这不一定正确,只是为了好理解)。
以下例子使用了ramda.js的函数式方法。(比如R.add())

容器:

Container

Maybe

Left

Right

IO

函数式方法:

maybe

either

join

chain

liftA2

liftA3

id

trace

Container

Container.of(2).map(function(e) {
  console.log(e);
});

Maybe

     Maybe.of("Malkovich Malkovich").map(R.match(/a/ig));
        //=> Maybe(['a', 'a'])
     Maybe.of(null).map(R.match(/a/ig));
     //=> Maybe(null)
     Maybe.of({name: "Boris"}).map(R.prop("age")).map(R.add(10));
     //=> Maybe(null)
     Maybe.of({name: "Dinah", age: 14}).map(R.prop("age")).map(R.add(10));
     //=> Maybe(24)   

Left && Right

    Right.of("rain").map(function(str){ return "b"+str; });
    // Right("brain")
    Left.of("rain").map(function(str){ return "b"+str; });
    // Left("rain")
    Right.of({host: 'localhost', port: 80}).map(R.prop('host'));
    // Right('localhost')
    Left.of("rolls eyes...").map(R.prop("host"));
    // Left('rolls eyes...')

IO

    // io_window_ :: IO Window
    const io_window = new IO(function(){ return window; });
    const action=io_window.map(function(win){ return win.innerWidth });
    //执行容器存储的函数
    action.do();
    // 1080  宽度

容器的几个方法

of()

用于初始化一个容器

    Container.of(2)
map(f)
  • f {function} 对容器值进行操作的函数

调用容器的值

Container.of(2).map(function(e) {
  console.log(e);
})
//2
join()

剥离一层容器

    const mmo = Maybe.of(Maybe.of("nunchucks"));
    // Maybe(Maybe("nunchucks"))
    mmo.join();
    // Maybe("nunchucks")
chain()

相当于在map 后,紧跟着调用 join

ap(otherContainer)

这个我也讲不明白....23333

Container.of(R.add)
        .ap(Container.of(2))
        .ap(Container.of(2));
//Container {value: 4}

maybe(x,f,m)

这样就可以要么返回一个静态值,要么继续愉快地在没有 Maybe 的情况下完成交易。 maybe 使我们得以避
免普通 map 那种命令式的 if/else 语句: if(x !== null) { return f(x)
} 。

参数:

  • x {string} 容器值是null时的返回值

  • f {function} 要对容器进行的操作

  • m {functor} 容器

    
    untils.maybe(
            "Nothing!",
            function (e) {console.log(e);}
            ,Maybe.of(null)
        );
    //"Nothing!"
    untils.maybe(
            "This will not be shown",
            function (e) {console.log(e);}
            ,Maybe.of("I am the thing to be shown.")
        );
    //"I am the thing to be shown."

either(f,g,e)

用于错误处理

参数:

  • f {function} 程序出错时的处理
  • g {function} 正常的处理
  • e {object} 容器
untils.either(
        function (e) {console.log("Wrong",e)},
        function (e) {console.log("Normal",e)},
        Right.of("Normal.")
    );
//Normal Normal

untils.either(
        function (e) {console.log("Wrong",e)},
        function (e) {console.log("Normal",e)},
        Left.of("Wrong!")
    );

//Wrong Wrong!

join

剥离一层容器

容器方法join的函数式写法

参数:

  • mma {容器}
    const safeProp=R.curry(function (x,obj) {
        return new Maybe(obj[x]);
    });
    const getName=R.compose(console.log, untils.join, safeProp("name"));
    getName({name:"Tom"});
    // Tom

chain

容器方法chain 的函数式写法

const safeProp=R.curry(function (x,obj) {
        return new Maybe(obj[x]);
    });
    const safeHead=safeProp(0);
    const firstAddressStreet =R.compose(
        console.log,
        untils.join,
        R.map(safeProp('street')),
        untils.join,
        R.map(safeHead),
        safeProp('addresses')
    );
    firstAddressStreet({addresses: [{street: {name: 'Mulburry', number: 8402}, postcode: "WC2N" }]});
    // Maybe({name: 'Mulburry', number: 8402})
    
    const firstAddressStreet2 =R.compose(
            console.log,
            untils.chain(safeProp('street')),
            untils.chain(safeHead),
            safeProp('addresses')
        );
    
    firstAddressStreet2({addresses: [{street: {name: 'Mulburry', number: 8402}, postcode: "WC2N" }]});
    //Maybe({name: 'Mulburry', number: 8402})

id(x)

原封不动返回参数x

trace

用于编程时排错,相当于“断点”。

const toLower=function (str) {
        return str.toLowerCase();
    };
    const toUpper=function (str) {
        return str.toUpperCase();
    };

    const mix=R.compose(
        untils.trace("After toUpper:"),
        R.map(toUpper),
        untils.trace("After split:"),
        R.split("_"),
        untils.trace("After toLower:"),
        toLower
    );
    mix("World_Wide");
    
    //After toLower: world_wide
    //After split: (2) ["world", "wide"]
    //After toUpper: (2) ["WORLD", "WIDE"]

liftA2(f,functor1,functor2)

容器方法ap的函数式写法

参数:

  • f {function} 处理容器值的方法

  • functor1 {function} 一个容器

  • functor2 {function} 另一个容器

untils.liftA2(R.add,Container.of(2),Container.of(2));

//Container {value: 4}

liftA3

容器方法ap的函数式写法

参数:

  • f {function} 处理容器值的方法

  • functor1 {function} 一个容器

  • functor2 {function} 另一个容器

  • functor3 {function} 第三个容器

    const signIn=R.curry(function (username,password,rememberMe) {
        //do something...
        console.log(username,password,rememberMe);
    });

    untils.liftA3(signIn,Container.of("Tom"),Container.of("123"),Container.of(false));
    // Tom 123 false

开源协议


MIT