51 votes

Que signifient les effets algébriques dans le FP?

Ref:

J'ai cherché beaucoup de liens, mais il semble que personne ne puisse l'expliquer plus précisément. Quelqu'un pourrait-il donner un peu de code(javaScript) pour l'expliquer?

35voto

cheeesus Points 1542

Qu'est ce qu'un Algébriques Effet?

TL;DR: En bref, Algébriques sont les Effets d'un mécanisme d'exception qui permet à l' throwing fonction de continuer ses opérations.

Essayez de penser à Algébrique des Effets comme une sorte try / catch mécanisme, où l' catch gestionnaire n'est pas juste "gérer l'exception", mais est en mesure de fournir une entrée à la fonction qui a déclenché l'exception. L'entrée de l' catch gestionnaire est ensuite utilisé dans le lancement de la fonction, qui continue comme si il n'y a pas d'exception.

Quelques exemples de pseudo-code:

Considérons une fonction qui a besoin de certaines données pour effectuer sa logique:

function throwingFunction() {
    // we need some data, let's check if the data is here
    if (data == null) {
        data = throw "we need the data"
    }
    // do something with the data
}

Nous avons ensuite le code qui appelle cette fonction:

function handlingFunction() {
    try {
        throwingFunction();
    } catch ("we need the data") {
        provide getData();
    }
}

Comme vous le voyez, l' throw instruction est une expression à évaluer les données fournies par l' catch gestionnaire (j'ai utilisé le mot-clé provide d'ici, qui à ma connaissance n'existe pas dans tout langage de programmation d'aujourd'hui).

Pourquoi est-ce important?

Algébrique Effets sont très générales, et le concept de base. Ceci peut être vu par le fait que de nombreux concepts existants peuvent être exprimées dans Algébrique des Effets.

try/catch

Si nous avions Algébrique des Effets, mais pas d'Exceptions dans notre langage de programmation favori, nous pourrions simplement omettre l' provide mot-clé dans l' catch gestionnaire, et voilà, nous avons un mécanisme d'exception.

En d'autres termes, nous n'aurions pas besoin des Exceptions si nous avions Algébrique des Effets.

async/await

Regardez encore le pseudo-code ci-dessus. Supposons que les données dont nous avons besoin doit être chargé sur le réseau. Si les données n'est pas encore là, nous devrions normalement de retour d'une Promesse et d'utilisation async/await pour le manipuler. Cela signifie que notre fonction est une fonction d'asynchrone, ce qui ne peut être appelé à partir asynchrone fonctions. Cependant, Algébrique des Effets en sont capables comportement trop:

function handlingFunction() {
    try {
        throwingFunction();
    } catch ("we need the data") {
        fetch('data.source')
            .then(data => provide data);
    }
}

Qui a dit que l' provide mot-clé doit être utilisé immédiatement?

En d'autres termes, si nous avions eu Algébrique des Effets avant d' async/await, il n'y aurait pas besoin d'encombrer les langues avec eux. En outre, Algébrique Effets ne rendrait pas nos fonctions coloré - notre fonction ne devient pas asynchrone à partir de la langue de point de vue.

Aspect-Oriented Programming

Disons que nous voulons avoir un log énoncés dans notre code, mais nous ne savons pas encore qui de journalisation de la bibliothèque, il sera. Nous voulons juste que certains journal général consolidés (j'ai remplacé le mot-clé throw avec le mot-clé effect ici, pour le rendre un peu plus lisible noter que effect n'est pas un mot clé dans n'importe quelle langue, je le sais):

function myFunctionDeepDownTheCallstack() {
    effect "info" "myFunctionDeepDownTheCallstack exits"

    // do some stuff

    if (warningCondition) {
        effect "warn" "myFunctionDeepDownTheCallstack has a warningCondition"
    }

    // do some more stuff

    effect "info" "myFunctionDeepDownTheCallstack begins"
}

Et puis on peut se connecter selon le journal de cadre en quelques lignes:

try {
    doAllTheStuff();
}
catch ("info" with message) {
    log.Info(message);
}
catch ("warn" with message) {
    log.Warn(message);
}

De cette façon, le journal de l'énoncé et le code qui ne fait de l'exploitation forestière sont séparés.

Comme vous pouvez le voir, l' throw mot-clé n'est pas vraiment adapté dans le contexte de la très général Algébrique des Effets. Plus adapté mots clés serait effect (comme ici) ou d' perform.

D'autres exemples

Il y a d'autres existantes de la langue ou de la bibliothèque de constructions qui pourraient être facilement réalisé à l'aide de Algébriques Effets:

  • Les itérateurs avec yield. Un langage Algébrique des Effets n'a pas besoin de l' yield déclaration.
  • Réagir Crochets (c'est un exemple d'une construction au niveau de la bibliothèque - les autres sont des exemples de constructions de langage).

10voto

hashedram Points 386

Il est difficile d'acquérir une solide compréhension théorique de la algébrique des effets sans une base dans la catégorie de la théorie, donc je vais essayer d'expliquer son utilisation dans d'autres termes, éventuellement sacrifier un peu de précision.

Un calcul de l'effet est tout calcul qui comprend une modification de son environnement. Par exemple, des choses comme la capacité totale du disque, la connectivité réseau sont les effets externes, qui jouent un rôle dans les opérations, comme la lecture/écriture de fichiers ou l'accès à une base de données. Rien qu'une fonction produit, en plus de la valeur qu'il calcule, est un calcul de l'effet. Du point de vue de la fonction, encore une autre fonction qui accède à la même mémoire que cette fonction ne peut être considérée comme un effet.

C'est la définition théorique. Pratiquement, il est utile de penser à l'effet que toute interaction entre une sous-expression et une centrale de contrôle qui gère les ressources à l'échelle mondiale dans un programme. Parfois, une expression locale peut avoir besoin d'envoyer des messages à la centrale de contrôle pendant l'exécution, avec suffisamment d'informations pour qu'une fois la centrale de contrôle est fait, il peut reprendre la suspension de l'exécution.

Pourquoi faisons-nous cela? Parce que parfois, les grandes bibliothèques ont une très longue chaîne d'abstractions, ce qui peut être gênant. À l'aide de "algébrique des effets", nous donne une sorte de raccourci pour passer des choses entre les abstractions, sans passer par l'ensemble de la chaîne.

En pratique JavaScript exemple, prenons une bibliothèque d'INTERFACE utilisateur comme ReactJS. L'idée est que l'INTERFACE utilisateur peut être écrite comme une simple projection de données.

Ceci par exemple, serait la représentation d'un bouton.

function Button(name) {
  return { buttonLabel: name, textColor: 'black' };
}

'John Smith' -> { buttonLabel: 'John Smith', textColor: 'black' }

L'utilisation de ce format, nous pouvons créer une longue chaîne de composable abstractions. Comme

function Button(name) {
  return { buttonLabel: name, textColor: 'black' };
}

function UsernameButton(user) {
  return {
    backgroundColor: 'blue',
    childContent: [
      Button(user.name)
    ]
  }
}

function UserList(users){
  return users.map(eachUser => {
    button: UsernameButton(eachUser.name),
    listStyle: 'ordered'
  })
}

function App(appUsers) {
  return {
    pageTheme: redTheme,
    userList: UserList(appUsers)
  }
}

Dans cet exemple, les quatre couches d'abstraction composé ensemble.

App -> UserList -> UsernameButton -> Bouton

Maintenant, supposons que, pour l'un de ces boutons, j'ai besoin d'hériter le thème de couleur de quelle que soit la machine sur laquelle il tourne. Dire, les téléphones mobiles ont un texte en rouge, tandis que les ordinateurs portables ont le texte en bleu.

Le thème de données est dans la première abstraction (App). Il doit être mis en œuvre dans la dernière abstraction (Bouton).

L'ennuyeux façon, serait de passer sur le thème des données, à partir de l'App à Bouton, la modification de chaque et chaque abstraction le long du chemin.

Application passe thème de données à UserList UserList passe à UserButton UserButton passe à Bouton

Il devient évident que dans les grandes bibliothèques avec des centaines de couches d'abstraction, c'est une énorme douleur.

Une solution possible est de passer sur l'effet, par le biais d'un effet spécifique de gestionnaire et de le laisser continuer quand il en a besoin.

function PageThemeRequest() {
  return THEME_EFFECT;
}

function App(appUsers) {
  const themeHandler = raise new PageThemeRequest(continuation);
  return {
    pageTheme: themeHandler,
    userList: UserList(appUsers)
  }
}

// ...Abstractions in between...

function Button(name) {
  try {
    return { buttonLabel: name, textColor: 'black' };
  } catch PageThemeRequest -> [, continuation] {
    continuation();
  }
}

Ce type d'effet de manutention, d'où une abstraction dans une chaîne peut suspendre quoi faire (thème de la mise en œuvre), d'envoyer les données nécessaires à la commande centrale (App, qui a accès à des thématisation), et transmet les données nécessaires pour la suite, est extrêmement simpliste exemple de manipulation des effets algébriquement.

7voto

Peter Points 713

Aussi loin que je comprends le sujet, algébrique des effets êtes actuellement un universitaire/concept expérimental qui vous permet de modifier certains éléments de calcul (comme les appels de fonction, des instructions d'impression, etc.) appelé "effets" à l'aide d'un dispositif qui ressemble throw catch

L'exemple le plus simple je pense, dans un langage comme JavaScript, c'est de modifier le message de sortie dans permet de dire console.log. Supposé que vous voulez ajouter "un Message de Débogage:" en face de tous vos console.log des déclarations, pour quelque raison que ce soit. Ce serait la difficulté à en JavaScript. Fondamentalement, vous devez appeler une fonction sur chaque console.log comme:

function logTransform(msg) { return "Debug Message: " + msg; }
console.log(logTransform("Hello world"));

Maintenant, si vous avez beaucoup d' console.log déclarations de chacun d'entre eux doit être changé si vous voulez introduire le changement dans l'exploitation forestière. Aujourd'hui, le concept de algébriques d'effets vous permettent de gérer l ' "effet" de console.log sur le système. Pensez-y comme console.log lancer une exception avant de l'invocation et de cette exception (l'effet) des bulles et peut être manipulé. La seule différence est la suivante: Si non gérée, l'exécution sera tout simplement continuer comme rien ne s'est passé. Pas de quoi cela vous permet de faire est de manipuler le comportement de l' console.log dans l'arbitraire d'un champ (global ou seulement local) sans manipuler le réel appel à l' console.log. Pourrait ressembler à quelque chose comme ceci:

 try
 {
 console.log("Hello world");
 }
 catch effect console.log(continuation, msg)
 {
    msg = "Debug message: " + msg;
    continuation();
 }

Notez que ce n'est pas le JavaScript, je suis tout simplement faire de la syntaxe jusqu'. Comme algébriques sont les effets expérimentaux de construire, ils ne sont pas pris en charge nativement dans n'importe quelle langage de programmation que je connais (il y a cependant plusieurs expérimentale des langues comme l'eff https://www.eff-lang.org/learn/). J'espère vous faire une bonne compréhension de la façon dont ma fait de code est destiné à travailler. Dans le try catch bloquer l'effet que peut être jeté en console.log peut être manipulé. La continuité est un jeton de construire ce qui est nécessaire afin de contrôler le flux normal devrait se poursuivre. Il n'est pas nécessaire d'avoir une telle chose, mais il vous permettra de faire des manipulations avant et après l' console.log (par exemple, vous pouvez ajouter un message de journal après chaque console.le journal).

Dans l'ensemble algébrique effets sont un concept intéressant qui permet à de nombreux problèmes du monde réel dans le codage, mais il peut aussi présenter certains pièges, si les méthodes soudain se comportent différemment que prévu. Si vous souhaitez utiliser algébrique des effets de droit maintenant en JavaScript, vous devez écrire un cadre de travail pour vous-même et vous ne serez probablement pas en mesure d'appliquer algébrique des effets des fonctions de base telles que l' console.log de toute façon. Fondamentalement, tout ce que vous pouvez faire maintenant est d'explorer le concept abstrait de l'échelle et de penser ou d'apprendre l'un de l'expérimentation des langues. Je pense que c'est aussi la raison pour laquelle beaucoup de l'introduction, les papiers sont tellement abstrait.

1voto

Akshay Nair Points 11

Vous pouvez vérifier les effets algébriques. Il s'agit d'une bibliothèque qui implémente beaucoup de concepts d'effets algébriques dans javascript en utilisant des fonctions de générateur, y compris les suites multiples. Il est beaucoup plus facile de comprendre les effets algébriques en termes de capture d'essai (effet d'exception) et les fonctions du générateur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X