PureScript

De Viquipèdia
Jump to navigation Jump to search
Infotaula de llenguatge de programacióPureScript
Tipus llenguatge de programació
Disseny Phil Freeman[1][2]
Paradigma de programació programació funcional amb avaluació estricta.[3]
Darrera versió estable 0.11.7[4]
Influenciat per Haskell, JavaScript
Modifica dades a Wikidata

PureScript és un llenguatge de programació funcional de codi obert basat en el llenguatge Haskell adaptat a un substrat JavaScript amb especificitats de Node.js, del qual pren els tipus bàsics, l'avaluació estricta per defecte, amb una sintaxi lleugerament diferent al Haskell estàndard, i unes classes numèriques amb pedigrí matemàtic (L'equivalent de Num del Haskell és Ring, denotant l'estructura d'anell, el de Fractional és Field, el nom anglosaxó per al Cos, l'equivalent de Integral és EuclideanRing, anell euclidià).[3]

En no comprometre's amb l'estàndard de Haskell, pot prescindir del RunTimeSystem que GHCJS emula oferint un resultat més lleuger i, a més a més, humanament llegible, incorporant extres com registres extensibles i efectes coŀlaterals més desgranats distingint els efectes que el Haskell engloba dins IO.[5]

S'en pot fer ús per aplicacions a consola, en pàgines web i també en aplicacions de servidor basades en Node.js.

Després de l'èxit d'Elm en el desenvolupament d'interfícies d'usuari, PureScript apareix com una base més potent tècnicament, donat que Elm ha seguit un camí reduccionista per simplificar-ne l'ús evitant els predicats en els paràmetres de tipus (ús d'interfícies).[6]

L'utilitzen comercialment per la creació d'entorns de desenvolupament d'interfícies d'usuari en pàgines web, com es detalla tot seguit.

Metodologies per generar interfícies d'usuari[modifica]

Utilitzen la programació reactiva per generar pàgines web automodificables, amb arquitectures en llenguatge PureScript basats en la funcionalitat aportada per ReactJS i la interacció amb servidors web de dades JSON, HTML o bé XML:[7][8]

  • Thermite[9] és una realització de Phil Freeman per embolcallar la funcionalitat més comuna de ReactJS.[7][10] Permet la combinació de components amb lents sobre l'estat i prismes (lents sobre tipus suma) sobre les accions.
  • PureScript Pux[11] és una arquitectura PureScript també basada en el sistema ReactJS que vol imitar la metodologia de Elm. Proposa separació de components per mòduls amb tractament manual de la combinació.[12][13] Actualment té problemes de rendiment segons mostra la seva web.
  • Halogen[14] hi introdueix el patró observador per facilitar la comunicació entre components pares i fills. També és de codi obert i desenvolupat per la companyia Slamdata.[15]
  • Optic UI[16] és un marc de desenvolupament d'interfícies d'usuari basat en lents.[17]

Entorn de desenvolupament[modifica]

Disposa de compilador, intèrpret i avaluador en-línia.

Requereix el gestor de Node.js "npm", i l'eina "pulp" i el gestor de paquets "bower".[18][19]

El rebost de biblioteques és el rebost Pursuit que també conté un cercador de l'API.

Rerefons de compilació[modifica]

Especificitats del llenguatge[modifica]

Vegeu ref.[3]

Algunes construccions esbiaixades cap al JavaScript i diferents del Haskell:

$ pulp repl  -- engega l'intèrpret

PSCi, version 0.11.7
Type :? for help
import Prelude

-- el tipus dels literals numèrics és fix, a diferència del Haskell on el tipus depèn de l'estructura algebraica requerida per l'operador.

> :t [1,2,3]   -- el tipus dels literals amb claus rectang. és (Array a), com al JavaScript, no pas com al Haskell
Array Int

> :t []  -- les claus buides denoten un Array buit. Per a les llistes cal fer servir Nil
forall t1. Array t1

> :t true -- els valors de l'àlgebra de Boole van en minúscules i el tipus és "Boolean", com al JS i no "Bool" com al Haskell
Boolean

> :t 1.5  -- el tipus dels literals Reals és Number, com al JS, i no Float/Double
Number 

-- L'operador (:) està definit tant per (Array a) Data.Array com per (List a) (Data.List)
> :t 1:2:[]
Array Int

> import Data.Array ((..)) -- l'operador dels rangs (..) també està definit per a ambdós
> :t 1..5                  -- els rangs no porten claus
Array Int                  -- el tipus dependrà de la signatura de l'operador visible

> :clear  -- reset de l'intèrpret
> import Data.List (List(..), (:))
> :t 1:2:Nil       -- amb (:) de Data.List això és una llista
List Int

> import Data.List.Lazy as LL   -- l'"import" amb sobrenom evita la incorporació del contingut a l'espai de noms. Equival en Haskell a "import qualified"
> LL.fromFoldable (1:2:Nil)     -- convertim a Lazy la llista estricta
fromStrict ((Cons 1 (Cons 2 Nil)))

> import Data.List as LS
> import Data.List.Lazy ((:))

> f :: Int -> LL.List Int
-- genera estrictament tots els elements d'una llista Lazy 
-- vegeu més avall seqüències definides recursivament amb avaluació tardana
> f x | x > 0 = x : f (x-1)   
>     | otherwise = LL.nil    -- llista buida

-- consum d'una llista tardana

import Data.List.Lazy (step, Step( Nil, Cons))    -- step força la desconstrucció

-- cal declarar totes les vars. d'una declaració de tipus a l'inici amb "forall" o bé el caràcter matemàtic ∀

mostraNElems :: forall a. Show a => Int -> LL.List a -> String    
mostraNElems n xs = go n (step xs)
  where
    go _ Nil = "Nil"
    go n (Cons x xs') | n > 0 = show x <> " : " <> go (n-1) (step xs')  -- (<>) és l'"append" de Data.Semigroup
                      | otherwise = ""

Les dades (data ...) estan completament avaluades, a diferència del Haskell estàndard on se'n retarda l'avaluació.

L'avaluació tardana de les expressions s'hi fa retardant l'avaluació amb una funció de Unit (Unit -> a), bé amb el mòdul Control.Lazy del paquet purescript-control,[22] o bé amb el tipus Lazy de Data.Lazy definit al paquet purescript-lazy.[23]

Hi ha llistes d'avaluació estricta (a Data.List) i d'avaluació tardana (a Data.List.Lazy), així com versions no-buides afegint .NonEmpty als corresponents noms de mòdul.[24]

Les conversions entre Number i Int no són al Prelude sinó al mòdul Data.Int de purescript-integers.[25]

toNumber :: Int -> Number

floor, ceil, round :: Number -> Int

Efectes coŀlaterals[modifica]

Els efectes coŀlaterals hi son més desgranats que al llenguatge Haskell, i es tracten amb un tipus extensible

  • amb la mònada Eff.[26]
    • CONSOLE: entrada/sortida a consola.[27]
    • FS: accessos al sistema de fitxers per als programes de servidor Node.js.[28]
    • DOM: interacció amb document web en una finestra del Navegador.[29]
    • TIMER: temporitzadors de JavaScript.[30]
    • EXCEPTION: excepcions.[31] Les excepcions es construeixen amb "error" i es disparen amb "throwException" i es cacen amb "catchException". throw strErr construeix i dispara.
  • amb la mònada Aff per als efectes asíncrons.[32]
    • Ajax.[33]
    • soŀlicituds HTTP multiplataforma {NodeJs, Navegador, altre} a la xarxa.[34]

Depuració[modifica]

  • La pila de traces de crida en cas d'excepció, hi ve incorporada (contràriament al compilador GHC de Haskell que requereix el RunTimeSystem d'ajustatge).

Seqüències definides recursivament[modifica]

Per exemple: següents x = x : següents (x+1) Per ser un llenguatge estricte, el càlcul provoca l'avaluació immediata del paràmetre recursiu i la consegüent petada de la pila.

Podem evitar-ho utilitzant l'expressió de la definició de Data.List.Lazy.cons que retarda, amb Data.Lazy.defer, l'avaluació del segon paràmetre.

$ pulp repl

PSCi, version 0.11.7
Type :? for help
import Prelude

> import Data.List.Lazy
> import Data.Lazy (defer)    -- defer :: (Unit -> a) -> Lazy a
 
> següents x = List $ defer \_ -> Cons x $ següents (x+1)

> show $ take 3 $ següents 0
"fromStrict ((Cons 0 (Cons 1 (Cons 2 Nil))))"

Segons l'article.[35]

Programa Hola Món[modifica]

module Main where

import Prelude        -- cal importar el mòdul Prelude explícitament

import Control.Monad.Eff (Eff)   
import Control.Monad.Eff.Console (CONSOLE, log)

-- cal declarar totes les vars. de la declaració de tipus a l'inici amb "forall" o bé el caràcter matemàtic ∀

main :: forall e. Eff (console :: CONSOLE | e) Unit   -- efectes amb tipus extensible
main = do
  log "Hola Món!"

Referències[modifica]

  1. About the author(anglès)
  2. GitHub - Phil Freeman(anglès)
  3. 3,0 3,1 3,2 Purescript - Diferències amb Haskell(anglès)
  4. edicions(anglès)
  5. taylor.fausak.me - El Perquè de PureScript(anglès)
  6. reasonablypolymorphic.com - Elm is wrong(anglès)
  7. 7,0 7,1 reactjs.org
  8. Youtube - Claudia Doppioslash - Building a Graphical IDE with Elm/Purescript(anglès)
  9. purescript-thermite(anglès)
  10. Guia a functorial.com - Building a Task List Application with Thermite(anglès)
  11. purescript-pux.org(anglès)
  12. Nesting component events(anglès)
  13. Guia a codeburst.io - Write React Components in PureScript with Pux
  14. Slamdata - purescript-halogen(anglès)
  15. Guia sobre Halogen a parsonsmatt.org(anglès)
  16. purescript-optic-ui(anglès)
  17. Guia a zrho.me - User Interfaces with Optics(anglès)
  18. PureScript - Getting started(anglès)
  19. Bower - A package manager for the web
  20. Purescript's c++ backend(anglès)
  21. Introducing PureScript Erlang backend(anglès)
  22. El paquet purescript-control(anglès)
  23. El paquet purescript-lazy(anglès)
  24. El paquet purescript-lists(anglès)
  25. El paquet purescript-integers(anglès)
  26. purescript-eff(anglès)
  27. purescript-console(anglès)
  28. purescript-node-fs(anglès)
  29. purescript-dom(anglès)
  30. purescript-js-timers(anglès)
  31. Mòdul Control.Monad.Eff.Exception(anglès)
  32. purescript-aff(anglès)
  33. purescript-affjax(anglès)
  34. purescript-requests(anglès)
  35. SchoolOfHaskell.org Building Lazy Lists in PureScript from recursive definitions(anglès)

Enllaços externs[modifica]