Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikibooksThe Free Textbook Project
Search

Elm programming language

50% developed
From Wikibooks, open books for an open world

Elm is afunctional programming language fordeclaratively creatingweb browser basedgraphical user interfaces.

Elm uses theFunctional Reactive Programming style andpurely functional graphical layout to build user interface without any destructive updates.

Description

[edit |edit source]

The primary implementation of Elm compiles to JavaScript and HTML, with the use of CSS styles.

In Elm, Functional Reactive Programming takes the place of event handlers and callbacks; it also manages all screen updates automatically. Purely functional graphical layout takes the place of working with the DOM. Elm also allowsMarkdown to be embedded directly.

Syntax and Semantics

[edit |edit source]

Elm adopts aHaskell styled syntax, with influences fromOCaml andFSharp. For example, "has type" is written with a single colon(:), and forward and backward function application use the(<|) and(|>) operators[1] where(f x) equals(f <| x) equals(x |> f).

Elm has extensible records[2] which safely provide much of the flexibility ofJavascript's object model.

The type system supports primitive types like integers and floats, structured data like tuples and records, and customADT's.[3]

Elm's version ofFunctional Reactive Programming is event-driven, meaning that updates are only performed as necessary. It shares the closest resemblance to Event-Driven FRP[4][5] and Arrowized FRP.[6][7]

The following program displays the position of the mouse as it moves around the screen, automatically updating the screen in real-time. Note: Elm'simport corresponds to Haskell'simport qualified.[8]

importGraphics.Elementexposing(..)importMouse-- qualified importmain=Signal.mapshowMouse.position

The value of main is displayed on screen. Function Graphics.Element.show turns any value into a displayable textual representation. Mouse.position is a value that changes over time, called a signal. Function Signal.map ensures that show is applied to Mouse.position every time the mouse moves.

Elm has a small but expressive set of language constructs, including if-expressions, let-expressions, case-expressions, anonymous functions, and list interpolation.[1][9]

Elm also has both a module system and a foreign function interface for JavaScript.[10]

The predefined functions are in thePrelude module.[11]

Values

[edit |edit source]

Values are immutable:

  • Bool, Int, Float.[11]
  • Char,[12] String,[11] (styled) Text.[13]
  • Time, Date.[14]
  • Element (html structural elements).[15]
  • graphic representations (called Forms), shapes and paths.[16]
toForm:Element->Form

>> toForm turns any Element into a Form. This lets you use text, gifs, and video in your collage. This means you can move, rotate, and scale an Element however you want.

Signals

[edit |edit source]

Signals are value varying items and have types as(Signal value_type).

They include time varying items (also calledbehaviors) and event driven sources.

-- current time, updated every t (from Time lib)every:Time->SignalTime-- current mouse position (from Mouse lib)position:Signal(Int,Int)

Html form input elements, may vary in style and state. Their generator functions mostly return a pair (element signal, status signal)[17] as in

-- create a checkbox with a given start state.checkbox:Bool->(SignalElement,SignalBool)

Dependent signals

[edit |edit source]

Dependent signals are likeformula cells in aspreadsheet. They may react to updates of their operand signals.

The one defined asmain starts the scanning of the dependency/reactiondirected graph to find the independent signal variables for inclusion in the source event loop.

You define signalformulas by using signal filter functions, or by applying lifted value functions to previously defined signals. To apply a function of N parameters, you have to lift the type of avalues function to asignals function, either through thelift<N> function, or by applyinglift to the function, followed by signal applicative terms as((~) signal) for functional parameters application exposed below.[18]

You can use a value in a signal position by lifting its type through theSignal.constant function.

From aHaskell perspective

[edit |edit source]
Signal as a Haskell's Functor instance
[edit |edit source]

See Functor class def.[19] From Elm's Signal library:[18]

-- lift a ''values'' function type to a ''signals'' function one-- similar to Haskell's ''fmap'' and ''Control.Applicative.liftA''lift:(a->b)->Signala->Signalb-- (<~) is an alias for lift
Signal as a Haskell's Applicative instance
[edit |edit source]

See Applicative class def.[20] From Elm's Signal library:[18]

-- lift a Valueconstant:a->Signala-- signal application(~):Signal(a->b)->Signala->Signalb-- sample from the second input every time an event occurs on the first input-- like Haskell's Control.Applicative.(*>) sequence actions discarding the first resultsampleOn:Signala->Signalb->Signalb------ lift<N>: to lift a function of N value parameters (defined lift2 to lift8)-- similar to Haskell's Control.Applicative.liftA<N>result_signal=liftNfun_N_arysignal1signal2...signalN-- equivalent with binary infix operatorsresult_signal=fun_N_ary<~signal1~signal2~...~signalN

Composable signal transformers. Automatons

[edit |edit source]

This is used to generate signal transformers as a chain.

Individual chain links, with type(Automaton input output) behave like computation (side effect) functions with only one parameter.

To chain two of them the input type of the follower must match the output result type of the precedent.

This concept is borrowed fromHaskell's arrows (effects sequencing through chaining ofmorphisms).[7][21]

You may apply them to aSignal with theAutomaton.run library function, specifying theAutomaton and a default result for the case of lack of input value.

From Elm's Automaton library:[22]

-- generator from a pure mapping functionpure:(a->b)->Automatonab-- generators from an initial state and a function of input and statestate:b->(a->b->b)->AutomatonabhiddenState:s->(a->s->(s,b))->Automatonab-- automaton applicationrun:Automatonab->b->Signala->Signalbresult_signal=runmyAutomatonresult_defaultinput_signal-- compose two automatons, chaining them together.(>>>):Automatonab->Automatonbc->Automatonac

Containers

[edit |edit source]

See ref.[23]

  • List, Set, Dict
  • Maybe (for optional parameters, and partially defined function results, as Just v or Nothing)
  • Either (error aware results, as Right correct_result or Left error)

To process a list of signals as one:

-- combine a list of signals into a signal of their value listSignal.combine:[Signala]->Signal[a]

Tools

[edit |edit source]
mkdirelm-compiler&&cdelm-compilercabal-devinstallelmelm-serverexportPATH=$PWD/cabal-dev/bin:$PATH

Examples

[edit |edit source]

Imported module members should be used qualified, except if listed atimport module (members...) or whenimport open is used for namespace inclusion.[8]

Non-varying

[edit |edit source]

Styled text

[edit |edit source]
importTextexposing(Text)importColorexposing(..)importGraphics.ElementasElemexposing(Element)-- qualified importunstyledText:TextunstyledText=Text.fromString"test1"styleIt:Text->TextstyleIt=(Text.typeface["serif"])>>(Text.colorred)-- (f <| x = f x), used to avoid parenthesesalignTest:Int->ElementalignTestcommonWidth=letelem1=Elem.widthcommonWidth<|Elem.justified<|styleItunstyledTextelem2=Elem.widthcommonWidth<|Elem.centered<|styleIt<|Text.fromString"test2"elem3=Elem.widthcommonWidth<|Elem.rightAligned<|styleIt<|Text.fromString"test3"inElem.flowElem.down[elem1,elem2,elem3]main:Elementmain=alignTest200

You may try it in theonline editor/compiler/executor.

Polymorphism on Record types

[edit |edit source]

See records.[24]

moduleMyModulewhereimportColortypeNameda={a|name:String}-- records with a ''name'' fieldgetName:Nameda->StringgetName{name}=namedude={name="John Doe",age=20}lady={name="Jane Doe",eyesColor=Color.blue}names:[String]names=[getNamedude,getNamelady]fullData=[showdude,showlady]staticElement:ElementstaticElement=flowdown<|mapplainText["Names: "++shownames,showfullData]main=staticElement
  • embedding it in adiv element
<!DOCTYPE HTML><!-- MyModule.html --><html><head><metacharset="UTF-8"><title>MyModule</title><!-- elm-runtime.js and js compiled modules --><scripttype="text/javascript"src="/your-install-directory/cabal-dev/share/Elm-N.N.N.N/elm-runtime.js"></script><scripttype="text/javascript"src="MyModule.js"></script></head><body><divid="myId"style="width:100;height:100;"></div><!-- Elm container must be a "div" element and must be empty --><scripttype="text/javascript">varmyContainer=document.getElementById('myId');Elm.embed(Elm.MyModule,myContainer);</script><noscript>Javascript is not enabled</noscript></body></html>
  • compile and test offline
# compile to Javascript$elm--make-s--only-jsMyModule.elm# run$browserMyModule.html

Parameterizing an Elm script

[edit |edit source]

Theport FFI (Foreign function interface withJavaScript) feature[25] gives the opportunity to supply parameters at thehtml level.

moduleElmMainwhereportarg1:Stringportarg2:Intportarg3:[String]implode:[String]->Stringimplode=concat.intersperse", "main=asText<|implode[arg1,showarg2,implodearg3]
<!DOCTYPE HTML><html><head><metacharset="UTF-8"><title>Title</title><!-- elm-runtime.js and js compiled modules      (if compiled with --make the ElmMain.js contains also the possibly imported user modules) --><scripttype="text/javascript"src="/your-install-directory/cabal-dev/share/Elm-N.N.N.N/elm-runtime.js"></script><scripttype="text/javascript"src="ElmMain.js"></script></head><body><divid="myId"style="width:100;height:100;"></div><!-- Elm container must be a "div" element and must be empty --><scripttype="text/javascript">varmyPorts={arg1:"do re mi",// after "The Jackson five" "abc" lyricsarg2:123,arg3:["abc","you and me"]};varmyContainer=document.getElementById('myId');Elm.embed(Elm.ElmMain,myContainer,myPorts);</script><noscript>Javascript is not enabled</noscript></body></html>

Signals (varying) examples

[edit |edit source]
  • lift: is likeHaskell'sfmap for Signals
lift:(a->b)->Signala->Signalb
  • lift<N> : applies a function of N values to N Signals; it acts likeHaskell's ApplicativeliftA<N>.[26]
  • (<~) and (~) are Elm replacements for Haskell's infix Applicative operators (<$>) and (<*>).[27]

Tictac varying graphics

[edit |edit source]

Using Graphics.Collage library.[16]

myShape1:ShapemyShape1=circle30myShape2=rect6060myForm1:FormmyForm1=outlined(dashedgreen)myShape1myForm2=outlined(solidred)myShape2forms:[Form]forms=[myForm1|>move(10,-10),myForm2|>move(30,-30)|>rotate(degrees45)|>scale1.5,plainText"mytext"|>toForm|>move(20,-20)|>rotate(degrees30)|>scale2]mapRotate:Float->[Form]->[Form]mapRotatet=letf=rotate<|degrees<|t*10inmapf-- let's define the left-to-right function composition operatorf>>g=g.f-- time signal in truncated secondstictac:SignalFloattictac=letf=inSeconds>>truncate>>toFloatinevery(2*second)|>liftfmain:SignalElementmain=constantforms|>lift2mapRotatetictac|>lift3collage(constant200)(constant200)-- equivalent with (<~) and (~) infix operatorsmain=letsignal1=mapRotate<~tictac~constantformsincollage<~constant200~constant200~signal1-- equivalent using ''constant'' to lift function typesmain=letsignal1=constantmapRotate~tictac~constantformsinconstantcollage~constant200~constant200~signal1

Password double field retype checker

[edit |edit source]

With color changing submit button.

importGraphics.InputasInputimportGraphics.ElementasElem-- button color modifier (pointfree)passwdOkColour:String->String->Element->ElementpasswdOkColourpasswd1passwd2=ifpasswd1==passwd2&&lengthpasswd1>=6thenElem.colorgreenelseElem.colorreddisplayfield1Elemfield2ElemsubmitButtonElem=field1Elem`above`field2Elem`above`submitButtonElemdynamicElement:SignalElementdynamicElement=let(field1ElemSignal,fld1StateSignal)=Input.password"Type password (min. 6 characters)!"labeledField1Signal=letprependLabel=beside(plainText"passwd: ")inliftprependLabelfield1ElemSignal(field2ElemSignal,fld2StateSignal)=Input.password"Retype password!"labeledField2Signal=letprependLabel=beside(plainText"control: ")inliftprependLabelfield2ElemSignal(submitButton,pressedSignal)=Input.button"Submit"coloredButSignal=constantsubmitButton|>lift3passwdOkColourfld1StateSignalfld2StateSignalinlift3displaylabeledField1SignallabeledField2SignalcoloredButSignalmain=dynamicElement

Note, as of Elm 0.10 Strings are no longer lists of characters, so the above becomes something more like this:

importGraphics.InputasInputimportGraphics.ElementasElemimportStringasS-- button color modifier (pointfree)passwdOkColour:String->String->Element->ElementpasswdOkColourpasswd1passwd2=ifS.lengthpasswd1>=6&&passwd1==passwd2thenElem.colorgreenelseElem.colorreddisplayfield1Elemfield2ElemsubmitButtonElem=field1Elem`above`field2Elem`above`submitButtonElemprependLabel=beside.plainTextdynamicElement:SignalElementdynamicElement=let(field1ElemSignal,fld1StateSignal)=Input.password"Type password (min. 6 characters)!"labeledField1Signal=lift(prependLabel"passwd: ")field1ElemSignal(field2ElemSignal,fld2StateSignal)=Input.password"Retype password!"labeledField2Signal=lift(prependLabel"control: ")field2ElemSignal(submitButton,_)=Input.button"Submit"coloredButSignal=constantsubmitButton|>lift3passwdOkColourfld1StateSignalfld2StateSignalinlift3displaylabeledField1SignallabeledField2SignalcoloredButSignalmain=dynamicElement

References

[edit |edit source]
  1. abThe Syntax of Elm
  2. Elm - Extensible Records
  3. Elm - Getting started with Types
  4. Wan, Zhanyong; Taha, Walid;Hudak, Paul (2002). "Event-Driven FRP".Proceedings of the 4th International Symposium on Practical Aspects of Declarative Languages: 155–172.
  5. Elm - What is Functional Reactive Programming?
  6. Attention: This template ({{cite doi}}) is deprecated. To cite the publication identified by doi:10.1145/581690.581695, please use {{cite journal}} with|doi=10.1145/581690.581695 instead.
  7. abElm - The Libraries You NeedAutomaton as an arrow implementation
  8. abVersion 0.8 release notes Section "Importing modules"
  9. About Elm Elm features
  10. Elm - JavaScript Integration
  11. abcdElm's Prelude
  12. Char library
  13. Text library
  14. Date library
  15. Element library
  16. abCollage library
  17. Graphics.Input library
  18. abcSignal library
  19. Haskell class Functor def.
  20. Haskell class Applicative def.
  21. Haskell Arrows introduction
  22. Automaton library
  23. Documentation
  24. Syntax - records
  25. JavaScript FFI
  26. Haskellwiki - Applicative functor
  27. Elm v.0.7 release notes Section: "Do you even lift?"

External links

[edit |edit source]
Retrieved from "https://en.wikibooks.org/w/index.php?title=Elm_programming_language&oldid=4482560"
Categories:
Hidden categories:

[8]ページ先頭

©2009-2025 Movatter.jp