Add Two Values Wrapped inside Option Monad - fp-ts

If I have two Option monads containing numbers, how can I add them together whilst not exiting the monad?
import { fromNullable, pipe, chain, map } from 'fp-ts/lib/Option'
let c1 = fromNullable(10)
let c2 = fromNullable(20)
// This is where I'm stuck. I would expect c3 to be an Option<number> containing 30.
let c3 = pipe(c1, chain(map((x) => x + c2))
Thank you :-)

You should use a sequence:
const c1 = Option.some(10);
const c2 = Option.some(20);
assertEquals(Array.sequence(Option.option)([c1, c2]), Option.some([10, 20]));
Look at https://fsharpforfunandprofit.com/posts/elevated-world-4/#sequence for explainations.

You are missing some pipe indirection in the snippet above. This will work:
import { option } from "fp-ts";
import { pipe } from "fp-ts/function";
declare const c1: option.Option<number>;
declare const c2: option.Option<number>;
const c3 = pipe(
c1,
option.chain(c1 =>
pipe(
c2,
option.map(c2 => c1 + c2)
)
)
);
There are various alternatives depending on the context/usage. Here are a few
Using Do from fp-ts-contrib:
import { Do } from "fp-ts-contrib/lib/Do";
const c3b = Do(option.option)
.bind("c1", c1)
.bind("c2", c2)
.return(({ c1, c2 }) => c1 + c2);
Using sequenceS from the Apply module:
import { sequenceS } from "fp-ts/Apply";
const c3c = pipe(
sequenceS(option.option)({ c1, c2 }),
option.map(({ c1, c2 }) => c1 + c2)
);

I came up with the following.
import {pipe} from 'fp-ts/lib/function'
import { getFoldableComposition } from 'fp-ts/Foldable'
import { array } from 'fp-ts/Array'
import { option,fromNullable } from 'fp-ts/Option'
import { monoidSum } from 'fp-ts/Monoid'
const F = getFoldableComposition(array, option)
let c1 = fromNullable(10)
let c2 = fromNullable(20)
let c3 = fromNullable(undefined)
let c4 = fromNullable(undefined)
// returns 30
F.reduce([c1,c2],0, monoidSum.concat) //?
// alternatively, also returns 30
F.reduce([c1,c2],0, (i,j)=>i+j) //?
// The above unwarp the result though. To return as the monad need to lift the result
// returns some(30)
pipe(F.reduce([c1,c2],0, (i,j)=>i+j), fromNullable) //?
// returns some(0)
pipe(F.reduce([c3,c4],0, (i,j)=>i+j), fromNullable) //?

Related

What's the type of arguments in sort method (typescript and react)

const [search] = useSearchParams()
const sort = search.get('sort')
export interface Note {
id?: string | any
author: string
title: string
category: string
description: string
favourite: boolean
date: string
descLength: number
}
const sortedNotes = (notes: Note[]) => {
type sortProps = {
a: Note
b: Note
}
return notes.sort(({ a, b }: sortProps) => {
const { favourite, descLength, id } = a
const { favourite: favouriteB, descLength: descLengthB, id: id2 } = b
switch (sort) {
case 'favourite':
return favourite > favouriteB ? 1 : -1
case 'longest':
return descLength > descLengthB ? 1 : -1
case 'none':
return id - id2 ? 1 : -1
default
}
})
}
const sortingNotes = sortedNotes(notes)
const currentNotes = sortingNotes.slice(indexOfFirstNote, indexOfLastNote)
I have tried to create a sort system in a note app but I don't know what the expected argument is
Please check a photo, i dont know why that error is occured
Your first issue is in the arguments you are passing to notes.sort(). You are giving a single object sortProps which contains two fields, rather than giving it two objects.
//incorrect
notes.sort(({ a, b }: sortProps) => {})
//correct
notes.sort((a: Note, b: Note) => {})
The type sortProps should not be necessary any longer.
Your method also does not return anything (in effect, it returns undefined) when the switch statement executes its default code. Even if you don't think this will ever occur in practice, TypeScript forces you to either ensure this will happen via the type system or to put some valid default value in place.
const sortedNotes = (notes: Note[]) => {
return notes.sort((a: Note, b: Note) => {
const { favourite, descLength, id } = a
const { favourite: favouriteB, descLength: descLengthB, id: id2 } = b
switch (sort) {
case 'favourite':
return favourite > favouriteB ? 1 : -1
case 'longest':
return descLength > descLengthB ? 1 : -1
default:// includes case 'none'
return id - id2 ? 1 : -1
}
})
}
See the documentation.
Sort takes two arguments, a and b. You're passing it a single argument-- an object with a and b within the object.
Instead of
notes.sort(({ a, b }: sortProps) => {
Try
notes.sort((a, b) => {
Though I will say that this is the sort of thing more appropriate for consulting documentation for as opposed to posting a question. The documentation on all the built in methods in JavaScript is quite extensive.

Sorting in React Select

I'd like to know if it is possible to set the sorting by alphabetical and number order. Here is my code, and it only does the alphabetical sorting but not the numeric one.
resellerList.sort((a1, a2) => {
const b1 = a1.resellerName.toLowerCase();
const b2 = a2.resellerName.toLowerCase();
if (b1 == b2) return 0;
if (b1 > b2) return 1;
return -1;
})
Here is a solution if the names always starts with 'client' following a number as in your example.
// input = 'client 6' then output = 6
const sliceAndParseInt = client => {
const client = client.resellerName.toLowerCase()
return parseInt(client.slice(6))
}
const sorted = resellerList.sort((a, b) => {
if (sliceAndParseInt(a) > sliceAndParseInt(b)) return 1
if (sliceAndParseInt(a) < sliceAndParseInt(b)) return -1
return 0
})
Otherwise, names are not always following the same convention unlike your example, you should change all the numbers to an equal length, e.g. 1 to 01;
'14' > '2' # return false
'14' > '02' # return true
Regards:)

Using a variable in more than 1 file

TL:DR - I need help using a variable in more than 1 file
Currently I have a bot that counts how many times the word ":p" has been used. It adds that number to the variable "numberofp". On a separate file I want to call the variable on an embed but it says numberofp is undefined. Code is below. If you would like more code just ask!
code for index.js
// variables
var numberofp = 0;
client.on('message', (message) => {
if(message.author.id = 714544589305806868){
if(message.content.includes(':p')){
numberofp = numberofp + 1;
console.log('Porsha_boy said :p, so far it has been sent this many times:', numberofp);
}
}
})
Code for embed
const db = require("quick.db")
const Discord = require('discord.js')
module.exports = {
name: 'rub',
description: 'a command that tells you what your ping is',
execute(message, args, Discord){
// Basic embed
var embed = new Discord.MessageEmbed()
.setAuthor(numberofp)
.setColor("#34BDE1")
console.log('working')
}
}
You need to export the variable to be visible from the module outside:
wordcounter.js
let counter = 0;
function increase(a = 1) {
counter += a;
}
function getCounter() {
return counter;
}
exports.increase = increase;
exports.getCounter = getCounter;
clientone.js
const wc = require('./wordcounter');
wc.increase();
wc.increase(2);
wc.increase(5);
clienttwo.js
const wc = require('./wordcounter');
wc.increase(1);
wc.increase(1);
wc.increase(5);
index.js
const wc = require('./wordcounter');
const c1 = require('./clientone');
const c2 = require('./clienttwo');
console.log(wc.getCounter());

Not able to change state properties of redux reducer in function call

I have this redux reducer case, which has multiple conditions to work with. I am getting issue in changing value of state properties.
//code explaination:
In the second condition I am checking if action.hoverIndex > action.dragIndex, and if the condition is true then it creates "td" variable to hold the new state. After state change I have to make some changes in the properties of the state.
In the else part of the 2nd condition when I change the properties of "td" by assigning new value in for loop, it works as expected, but same thing when I try in "nestedConditionHandler" it does not work. not sure what is causing this issue.
const cmdArray = [
"ECommand",
"BCommand",
"CCommand",
"DCommand",
];
const cmdPair = {
ECommand: "EndE",
BCommand: "EndB",
CCommand: "EndC",
DCommand: "EndD",
};
const notFirstCommand = [
"PCommand",
"QCommand",
"XCommand"
];
case actionTypes.UPDATE_COMMAND_WORKFLOW:
// Deep clone of current state
const temp = cloneDeep(state);
// Draged command state
const dragCard = temp[action.dragIndex];
const tempDragCard = cloneDeep(dragCard);
// hovered command state
const hoverCard = temp[action.hoverIndex];
const tempHoverCard = cloneDeep(hoverCard);
//condition one
if (
action.hoverIndex === 0 &&
notFirstCommand.includes(dragCard.class_name)
) {
return temp;
}
//condition 2
// command drag from top to bottom
if (action.hoverIndex > action.dragIndex) {
const td = update(temp, {
$splice: [
[action.dragIndex, 1],
[action.hoverIndex, 0, tempDragCard],
],
});
let startIndex;
let endconditionIndex;
// for nested commands
const nestedConditionHandler = (i, currState) => {
startIndex = i + 1;
endconditionIndex = td.indexOf(
td.find((cur) => cmdPair[currState.class_name] === cur.class_name)
);
while (startIndex < endconditionIndex) {
const tempTd = td[startIndex];
console.log(tempTd);
console.log(currState.indent + 1);
td[startIndex].indent = currState.indent +1
td[startIndex].parentId = currState.parentId
if (cmdArray.includes(td[startIndex].class_name)) {
nestedConditionHandler(startIndex, td[startIndex]);
}
startIndex += 1;
}
};
if (
dragCard.class_name === "ECommand" ||
dragCard.class_name === "EfCommand"
) {
for (let i = action.dragIndex; i < action.hoverIndex; i++) {
td[i].indent = dragCard.indent + 1;
td[i].parentId = dragCard.parentId;
}
} else {
for (let i = action.dragIndex; i < action.hoverIndex; i++) {
td[i].indent = dragCard.indent;
td[i].parentId = dragCard.parentId;
if (cmdArray.includes(td[i].class_name)) {
nestedConditionHandler(i, td[i]);
}
}
}
return td;
}
// command drag from bottom to top , next condition

Sum values inside an array

I'm trying to sum the values inside an array depending on which levels they are but with no success for the moment.
Datas I'm working with ( named as the variable totalByLevel ) :
What I want :
Having each total per level inside 1 array, for example : ['total of 3 + 4', 'total of 6 + 7', etc...]
What I tried :
I tried to create an empty array and push the values from 3 + 4 into the array, which is working but not as intented.
Only the last values is kept in the array and all others are erased, if you have a fix for it I would really appreciate any help! Thank you in advance.
component.ts
for (const levelKey in this.totalByLevel ) {
if (this.totalByLevel .hasOwnProperty(levelKey)) {
const key = this.labelName[levelKey];
const value = this.totalByLevel [levelKey][Object.keys(this.totalByLevel [levelKey])[0]];
const value2 = this.labelName[Object.keys(this.totalByLevel [levelKey])[0]];
const value3 = this.totalByLevel [levelKey][Object.keys(this.totalByLevel [levelKey])[1]];
const value4 = this.totalByLevel [levelKey][Object.keys(this.totalByLevel [levelKey])[2]];
this.output_object[key] = value;
this.output_object2[key] = value2;
const sum = [];
if (value4 !== undefined || null) {
sum.push((+value + +value3 + +value4).toFixed(2));
console.log(sum, 'SUM 3');
this.totalPerCat = sum;
} else if (value4 === undefined || null) {
sum.push((+value + +value3).toFixed(2));
console.log(sum, 'SUM 2');
this.totalPerCat = sum;
} else if (value3 === undefined || null) {
sum.push(value);
console.log(sum, 'SUM 1');
this.totalPerCat = sum;
}
console.log(this.totalPerCat);
/* console.log(value3);
console.log(value4);
console.log(+value + +value3 + +value4, 'SUM');*/
}
}
});
Here you go:
const data={
2:{3:"3514.80", 4:"7259.32"},
5:{6:"864941.86", 7:"1076976.54"},
8:{"":"14145.69"},
9:{10:"223835.02", 11:"60978.31", 12:"5554.92"}
}
const result = Object.values(data).map(items => Object.values(items).map(val => Number(val)).reduce((a,b) => a + b, 0))
console.log(result)
You could use the funcitons Object.values() and Array reduce in combination. Try the following
var totalByLevel = {
2: {
3: '3514.80',
4: '7259.32'
},
5: {
6: '864941.86',
7: '1076976.54'
}
};
var sum = Object.values(totalByLevel).reduce((acc, curr) => {
acc.push(String(Object.values(curr).reduce((a, c) => a + Number(c), 0)));
return acc;
}, []);
console.log(sum);

Resources