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 🙏

© 2024 – Pkg Stats / Ryan Hefner

m-signal

v0.1.0

Published

Monadic signals for asynchronous and reactive programming

Downloads

5

Readme

#m-signal

Monadic signals for asynchronous and reactive programming. Still under development, but should be usable.

##API

signal(source)

Creates a signal. source should be a function that takes one argument: a function that source calls when it wants to add a value to the signal.

signal.unit(value)

Creates a signal with value as its only value. (Part of being a monad, and equivalent to monadic return.)

signal.combine(...signals)

Takes a number of signals and combines them into one signal that broadcasts the current value of each signal as an array when any signal changes.

signal.lift(f)

Takes a function and returns an equivalent where each argument and the return value are all signals containing the same type as the original function.

###Methods of signals

In the following descriptions, s is any signal. All methods return a new signal except for listen.

s.fmap(f)

Returns a signal with every value broadcast by s passed through the function f. Analogous to map for arrays.

s.bind(f)

f should be a function that takes a value broadcast by s and returns a signal. The signal returned by bind then broadcasts the values of these signals whenever one of them updates.

s.fold(f, i)

For each value from f, passes the previous return value of f and the new value to f and broadcasts the return value. i is used as the initial first argument to f.

s.apply(s2)

This only works if the values of s are functions. When s or s2 is updated, broadcasts the result of calling the current value of s with the current value of s2.

s.listen(f)

Whenever s broadcasts a value, f is called with that value. Note that the value can be the same as the previous one and that if s has already broadcast a value when listen is called, f will be immediately called with the current value of s.

###Types

(In my own imagined TypeScript/Haskell hybrid type system, hopefully it's comprehensible.)

type Signal<T> = {
	fmap: <U> (T => U) => Signal<U>,
	bind: <U> (T => Signal<U>) => Signal<U>,
	fold: <U> ((U, T) => U, U) => Signal<U>,
	apply: <U => V = T> Signal<U> => Signal<V>,
	listen: (T => void) => void
};
signal :: <T> ((T => void) => void) => Signal<T>;
signal.unit :: <U> U => Signal<U>
signal.combine :: <T, U,...> [Signal<T>, Signal<U>,...] => Signal<[T, U,...]>
signal.lift :: <T, U,...,R> ((T, U,...) => R) => ((Signal<T>, Signal<U>,...) => Signal<R>)

##Examples

###FRP

var signal = require('msignal');

function mouseSignal() {
	return signal(function(resolve) {
		window.addEventListener("mouseup", function(e) { resolve(false); });
		window.addEventListener("mousedown", function(e) { resolve(true); });
	});
}

// Logs the number of clicks
mouseSignal()
	.fold(function(sum, mouse) { return mouse ? sum + 1 : sum; }, 0)
	.listen(console.log.bind(console));

###Promise-y

var signal = require('msignal');

function ajaxGet(url) {
	return signal(function(resolve) {
		var xhr = new XMLHttpRequest();
		xhr.open("GET", url);
		xhr.onreadystatechange = function() {
			if (xhr.readyState === 4 && xhr.status === 200)
				resolve(xhr.responseText);
		};
		xhr.send();
	});
}

ajaxGet("http://reddit.com/r/javascript/about.json")
	.fmap(function(json) {
		return JSON.parse(json).data.description_html;
	})
	.listen(console.log.bind(console));