| สารบัญ |
|---|
| - รถตู้ ความหลากหลายของเทคโนโลยีเว็บ สำหรับการพัฒนาแอพข้ามแพลตฟอร์ม |
| เริ่มต้น |
| ส่วนประกอบของเว็บ |
| ⚡การเขียนโปรแกรมปฏิกิริยาการทำงาน (FRP) การเขียนโปรแกรมที่ใช้งานได้คืออะไร? ไดรฟ์รหัสการเขียนโปรแกรมที่ใช้งานได้อย่างไร |
| timeline |
| ⏱ประเภทที่ไม่มีค่าใช้จ่าย ประเภทโมฆะเป็นโมฆะและตัวเลือกคืออะไร? |
| ⏱ไทม์ไลน์เป็นโมฆะ |
| ⏱งานไทม์ไลน์ |
| ⏱งานไทม์ไลน์ concat |
| ⏱งานไทม์ไลน์หรือ |
| ⏱งานไทม์ไลน์และ |
| การอภิปราย |
import van from "vanjs-core"
const { a , p , div , li , ul } = van . tags
// Reusable components can be just pure vanilla JavaScript functions.
// Here we capitalize the first letter to follow React conventions.
const Hello =
( ) =>
div (
p ( "Hello" ) ,
ul (
li ( "?️World" ) ,
li ( a ( { href : "https://vanjs.org/" } , "?VanJS" ) ) ,
) ,
)
van . add ( document . body , Hello ( ) )ลองใช้ JSFIDDLE
module HelloApp
open Browser
open Browser. Types
open Fable. Core . JsInterop
open Van. Basic // import tags, add
let a : Tag = tags?a
let p : Tag = tags?p
let div : Tag = tags?div
let ul : Tag = tags?ul
let li : Tag = tags?li
let Hello =
fun _ ->
div [
p [ " Hello " ]
ul [
li [ " ?️World " ]
li [ a [{| href = " https://vanjs.org/ " |}; " ?VanJS " ]]
]
]
add [ document.body ; Hello ()]
|> ignoreการสาธิต
https://codepen.io/kentechgeek/pen/vwnovox
let Greeting : Tag =
fun list ->
let name : string = list [ 0 ]? name
div [ $ " Hello {name}! " ]
add [ document.body ; Greeting [{| name = " Ken " |}]]
|> ignore const Greeting : Component < { name : string } > =
( { name } ) =>
< div > Hello { name } ! </ div > ;
render ( ( ) => < Greeting name = "Ken" /> , document . body ) ; โครงการ VANFS มีรหัส Typescript บางรายการ
https://github.com/ken-okabe/vanfs/blob/main/van-api/ts/basic.ts
รหัส TS เพื่อวัตถุประสงค์ในการแปลงโดยใช้ JS Proxy:
// unary function ([a,b,c,...]) in F#
// -> n-ary function (a,b,c,...) in VanJS นี่อยู่ภายใต้ไดเรกทอรี van-api ซึ่งเป็นสิ่งจำเป็นและเราไม่ต้องการแก้ไขเพื่อให้สิ่งต่าง ๆ ทำงานได้
ผู้ใช้จะต้องติดตั้ง CSS หรือ ส่วนประกอบเว็บ ที่จำเป็น
VANJS ไม่ได้ให้การสนับสนุนการติดตั้งเฉพาะ Beuse เป็นเพียงวานิลลา
ในทางกลับกัน VANFS ชี้แจงกระบวนการทีละขั้นตอนดังต่อไปนี้:
ทุกสิ่งที่เราจำเป็นต้องปรับแต่งหรือนำเข้าอยู่ภายใต้ไดเรกทอรี Web-Imports
import {
provideFluentDesignSystem ,
fluentCard ,
fluentCheckbox
} from "@fluentui/web-components" ;
provideFluentDesignSystem ( )
. register (
fluentCard ( )
) ;
provideFluentDesignSystem ( )
. register (
fluentCheckbox ( )
) ; export let cssURLs = [
"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200"
] ;ไม่ว่ารหัสที่ต้องการทั้งหมดภายในโครงการ VANFS จะถูกรวบรวมไว้ในชุดวานิลลาเดียวโดยใช้นิทานและ VITE
let bindT = < A , B >
( monadf : ( a : A ) => Timeline < B > ) =>
( timelineA : Timeline < A > ) : Timeline < B > => {
let timelineB = monadf ( timelineA . lastVal ) ;
let newFn = ( a : A ) => {
nextT ( monadf ( a ) . lastVal ) ( timelineB ) ;
return undefined ;
} ;
timelineA . lastFns = timelineA . lastFns . concat ( [ newFn ] ) ;
return timelineB ;
} ;ใน TypeScript เมื่อเทียบกับ JavaScript แบบดั้งเดิมจำเป็นต้องมีขั้นตอนเพิ่มเติมเพื่อเพิ่มประเภทลายเซ็นให้กับตัวแปรฟังก์ชันและพารามิเตอร์ทั้งหมด สิ่งนี้มักจะท่วมท้น
let bindT =
fun monadf timelineA ->
let timelineB = timelineA.lastVal |> monadf
let newFn =
fun a ->
timelineB
|> nextT ( a |> monadf ) .lastVal
|> ignore
timelineA.lastFns <- timelineA.lastFns @ [ newFn ]
timelineBรหัส F# นั้นสะอาดกว่าและอ่านได้มากกว่ารหัส typeScript
ใน F#เราไม่ค่อยจำเป็นต้องเพิ่มประเภทด้วยตนเองด้วยการอนุมานประเภทที่ทรงพลัง สิ่งนี้ทำให้การพัฒนา F# รู้สึกคล้ายกับการเข้ารหัส JavaScript แบบดั้งเดิม
ในความเป็นจริงมันเป็นมากกว่านั้น
ในขณะที่โปรแกรมเมอร์อาจต้องการกำหนดประเภทวัตถุพื้นฐานที่เป็นกระดูกสันหลังของรหัสของพวกเขาในสถานที่อื่น ๆ หาก F# คอมไพเลอร์เตือนถึงความต้องการคำอธิบายประกอบประเภทด้วยตนเองโดยปกติ จะมีบางอย่างผิดปกติ
ใน F#หากคอมไพเลอร์ไม่สามารถอนุมานประเภทได้มักจะแนะนำว่าอาจมีความไม่สอดคล้องทางคณิตศาสตร์
ใน TypeScript หากคอมไพเลอร์ไม่สามารถอนุมานประเภทได้มักจะแนะนำข้อ จำกัด ในความสามารถในการอนุมานประเภท สิ่งนี้ทำให้ยากที่จะกำหนดสาเหตุที่แม่นยำของปัญหา
เป็นผลให้โปรแกรมเมอร์ F# ถูกนำไปสู่การเขียนรหัสที่สอดคล้องกันทางคณิตศาสตร์และเข้มงวด น่าเสียดายที่ประโยชน์นี้ ไม่ค่อย เกิดขึ้นใน TypeScript
F# โดยทั่วไปได้รับการยอมรับว่าทำงานบน. NET Framework แต่เช่นเดียวกับ TypeScript ถูกรวบรวมเป็น JavaScript F# ก็รวบรวมกับ JavaScript
TypeScript -> JavaScript
f# -> JavaScript
แม่นยำยิ่งขึ้น
พิมพ์ดีด
⬇คอมไพเลอร์ TypeScript กำลังทำงานบน node.js (npx tsc)
JavaScript ทำงานในเบราว์เซอร์
f#
⬇คอมไพเลอร์นิทานทำงานบน. NET (dotnet fable)
JavaScript ทำงานในเบราว์เซอร์
ดังนั้นกระดูกสันหลังของ Vanfs จึงเป็นนิทาน
| สารบัญ |
|---|
| - รถตู้ ความหลากหลายของเทคโนโลยีเว็บ สำหรับการพัฒนาแอพข้ามแพลตฟอร์ม |
| เริ่มต้น |
| ส่วนประกอบของเว็บ |
| ⚡การเขียนโปรแกรมปฏิกิริยาการทำงาน (FRP) การเขียนโปรแกรมที่ใช้งานได้คืออะไร? ไดรฟ์รหัสการเขียนโปรแกรมที่ใช้งานได้อย่างไร |
| timeline |
| ⏱ประเภทที่ไม่มีค่าใช้จ่าย ประเภทโมฆะเป็นโมฆะและตัวเลือกคืออะไร? |
| ⏱ไทม์ไลน์เป็นโมฆะ |
| ⏱งานไทม์ไลน์ |
| ⏱งานไทม์ไลน์ concat |
| ⏱งานไทม์ไลน์หรือ |
| ⏱งานไทม์ไลน์และ |
| การอภิปราย |
.NET SDK
node.js และ npm CLI หรือทางเลือก (Bun / deno / yarn ฯลฯ )
หากคุณยังใหม่กับ F# และใช้ VSCODE ให้อ่านการตั้งค่า F# บน VSCODE
โครงการ VANFS/Fable เป็นไฮบริดของ โครงการ F#.NET และ โครงการ NPM
ดู Fable Setup Documentaion
git clone https://github.com/ken-okabe/vanfs
cd vanfs
dotnet restore # .NET project setup
dotnet tool restore
npm i # npm project setup body {
font-family : sans-serif;
padding : 1 em ;
background-color : beige;
}การสาธิต
https://codepen.io/kentechgeek/pen/zyxqyxz
| สารบัญ |
|---|
| - รถตู้ ความหลากหลายของเทคโนโลยีเว็บ สำหรับการพัฒนาแอพข้ามแพลตฟอร์ม |
| เริ่มต้น |
| ส่วนประกอบของเว็บ |
| ⚡การเขียนโปรแกรมปฏิกิริยาการทำงาน (FRP) การเขียนโปรแกรมที่ใช้งานได้คืออะไร? ไดรฟ์รหัสการเขียนโปรแกรมที่ใช้งานได้อย่างไร |
| timeline |
| ⏱ประเภทที่ไม่มีค่าใช้จ่าย ประเภทโมฆะเป็นโมฆะและตัวเลือกคืออะไร? |
| ⏱ไทม์ไลน์เป็นโมฆะ |
| ⏱งานไทม์ไลน์ |
| ⏱งานไทม์ไลน์ concat |
| ⏱งานไทม์ไลน์หรือ |
| ⏱งานไทม์ไลน์และ |
| การอภิปราย |
VANFS สามารถใช้ประโยชน์จากแท็ก HTML ที่กำหนดเองที่จัดทำโดย ส่วนประกอบของเว็บ ด้วย ระบบการออกแบบ : Microsoft Fluent, Google Material Design ฯลฯ
import {
provideFluentDesignSystem ,
fluentCard ,
fluentCheckbox
} from "@fluentui/web-components" ;
provideFluentDesignSystem ( )
. register (
fluentCard ( )
) ;
provideFluentDesignSystem ( )
. register (
fluentCheckbox ( )
) ; body {
font-family : sans-serif;
padding : 1 em ;
background-color : beige;
}
. custom {
--card-width : 200 px ;
--card-height : 150 px ;
padding : 22 px ;
}Program.fs module WebComponentsApp
open Browser
open Browser. Types
open Fable. Core . JsInterop
open Van. Basic // import tags, add
let br : Tag = tags?br
// Define the fluent-card and fluent-checkbox tags
let fluentCard : Tag = tags? `` fluent-card ``
let fluentCheckbox : Tag = tags? `` fluent-checkbox ``
let List =
fun _ ->
fluentCard [
{| `` class `` = " custom " |}
// class is a reserved word in F#
// so we use backticks to escape it
fluentCheckbox [ " Did you check this? " ]
br []
fluentCheckbox [{| `` checked `` = true ; disabled = true |}; " Is this disabled? " ]
br []
fluentCheckbox [{| `` checked `` = true |}; " Checked by default? " ]
]
add [ document.body ; List ()]
|> ignoreเมื่อมีการเปลี่ยนแปลงครั้งใหญ่การทำความสะอาดโครงการนิทานบางครั้งก็จำเป็น
dotnet fable clean
dotnet fable watchnpx vite import '@material/web/textfield/filled-text-field.js' ;
import '@material/web/button/text-button.js' ;
import '@material/web/button/outlined-button.js' ; . custom3 {
--card-width : 460 px ;
--card-height : 150 px ;
padding : 20 px ;
}
. row {
align-items : flex-start;
display : flex;
flex-wrap : wrap;
gap : 16 px ;
}
. buttons {
justify-content : flex-end;
padding : 16 px ;
}
md-filled-text-field ,
md-outlined-text-field {
width : 200 px ;
} module MaterialUI
open Browser
open Browser. Types
open Fable. Core . JsInterop
open Van. Basic // import tags, add
let div : Tag = tags?div
let form : Tag = tags?form
let fluentCard : Tag = tags? `` fluent-card ``
let mdFilledTextField : Tag = tags? `` md-filled-text-field ``
let mdTextButton : Tag = tags? `` md-text-button ``
let mdOutlinedButton : Tag = tags? `` md-outlined-button ``
let Form =
fun _ ->
fluentCard [
{| `` class `` = " custom3 " |}
form [
div [
{| `` class `` = " row " |}
mdFilledTextField [
{|
label = " First name "
name = " first-name "
required = " "
autocomplete = " given-name "
|}
]
mdFilledTextField [
{|
label = " Last name "
name = " last-name "
required = " "
autocomplete = " family-name "
|}
]
]
div [
{| `` class `` = " row buttons " |}
mdTextButton [
{| `` type `` = " reset " |}
" Reset "
]
mdOutlinedButton [
{| `` type `` = " submit " |}
" Submit "
]
]
]
]
add [ document.body ; Form ()]
|> ignorenpx vite buildการสาธิต
https://codepen.io/kentechgeek/pen/kkylwgn?editors=1111
import '@material/web/icon/icon.js' ;
import '@material/web/iconbutton/icon-button.js' ; https://m3.material.io/styles/icons/overview
export let cssURLs = [
"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200"
] ;| สารบัญ |
|---|
| - รถตู้ ความหลากหลายของเทคโนโลยีเว็บ สำหรับการพัฒนาแอพข้ามแพลตฟอร์ม |
| เริ่มต้น |
| ส่วนประกอบของเว็บ |
| ⚡การเขียนโปรแกรมปฏิกิริยาการทำงาน (FRP) การเขียนโปรแกรมที่ใช้งานได้คืออะไร? ไดรฟ์รหัสการเขียนโปรแกรมที่ใช้งานได้อย่างไร |
| timeline |
| ⏱ประเภทที่ไม่มีค่าใช้จ่าย ประเภทโมฆะเป็นโมฆะและตัวเลือกคืออะไร? |
| ⏱ไทม์ไลน์เป็นโมฆะ |
| ⏱งานไทม์ไลน์ |
| ⏱งานไทม์ไลน์ concat |
| ⏱งานไทม์ไลน์หรือ |
| ⏱งานไทม์ไลน์และ |
| การอภิปราย |
VANFS อธิบายว่าเป็น
1: 1 การผูกจาก F# ถึง VANJS (เฟรมเวิร์ก UI ปฏิกิริยาขนาดเล็กที่ไม่มี React/JSX) + webcomponents + Micro FRP
หรือ
VANFS เป็นเทมเพลตโครงการ F# สำหรับการผูกโดยตรงแบบหนึ่งต่อหนึ่งของ VANJS
1: 1 การผูกเป็นความจริงอย่างแน่นอนภายในขอบเขตของคุณสมบัติพื้นฐานสำหรับการเขียน UIs แต่ไม่ใช่กรณีสำหรับการจัดการสถานะ
VANJS ผูกมัดวัตถุสถานะของมันกับองค์ประกอบ DOM ที่สอดคล้องกัน ซึ่งหมายความว่าเมื่อวัตถุสถานะอัปเดตองค์ประกอบ DOM ที่เกี่ยวข้องจะอัปเดตโดยอัตโนมัติเช่นกัน วิธีการนี้เป็นคุณสมบัติทั่วไปในห้องสมุด UI ที่ประกาศเช่น React, SolidJs ฯลฯ
นี่คือโครงสร้างที่เหมือนกันของ:
ดังนั้นนี่คือ FRP
ฟังก์ชั่นการเขียนโปรแกรมปฏิกิริยา (FRP) เป็นกระบวนทัศน์การเขียนโปรแกรมที่ใช้นิพจน์ทางคณิตศาสตร์โดยเฉพาะ การดำเนินการไบนารี โดยเฉพาะซึ่งเป็นวิธีการใช้การเขียน โปรแกรมปฏิกิริยา
| สารบัญ |
|---|
| - รถตู้ ความหลากหลายของเทคโนโลยีเว็บ สำหรับการพัฒนาแอพข้ามแพลตฟอร์ม |
| เริ่มต้น |
| ส่วนประกอบของเว็บ |
| ⚡การเขียนโปรแกรมปฏิกิริยาการทำงาน (FRP) การเขียนโปรแกรมที่ใช้งานได้คืออะไร? ไดรฟ์รหัสการเขียนโปรแกรมที่ใช้งานได้อย่างไร |
| timeline |
| ⏱ประเภทที่ไม่มีค่าใช้จ่าย ประเภทโมฆะเป็นโมฆะและตัวเลือกคืออะไร? |
| ⏱ไทม์ไลน์เป็นโมฆะ |
| ⏱งานไทม์ไลน์ |
| ⏱งานไทม์ไลน์ concat |
| ⏱งานไทม์ไลน์หรือ |
| ⏱งานไทม์ไลน์และ |
| การอภิปราย |
Timeline เป็นห้องสมุด FRP แบบสแตนด์อโลนโดยไม่มีการพึ่งพาคุณสมบัติ VANJS หรือ F# แบบอะซิงโครนัส Codebase เป็นการใช้งานฟังก์ชั่นบริสุทธิ์ขนาดกะทัดรัดของรหัสประมาณ 30-40 บรรทัด
Timeline<'a>record Timeline < 'a >
val mutable lastVal : 'a
val el : StateElement < 'a >| สนาม | คำอธิบาย | van.state |
|---|---|---|
lastVal | ค่าสุดท้ายของไทม์ไลน์ | State.val |
el | องค์ประกอบ DOM ปฏิกิริยาของไทม์ไลน์ | State |
Timeline<'a>Timeline'a -> Timeline < 'a > let counter = van . state ( 0 ) ;
console . log ( counter . val ) ;
// 0 let counter = Timeline 0
console.log counter.lastVal
// 0 พิจารณา Timeline เป็นคอนเทนเนอร์เฉพาะสำหรับค่าคล้ายกับเซลล์ในแอพสเปรดชีต
let double = fun a -> a * 2
let timelineA = Timeline 1
let timelineB =
timelineA |> mapT double
console.log timelineB.lastVal
// 2รหัสนี้สำหรับการดำเนินการไบนารีนั้นสอดคล้องกับการใช้งานพื้นฐานของแอพสเปรดชีต
นี่คือโครงสร้างที่เหมือนกันของ:
let double = a => a * 2 ;
let arrayA = [ 1 ] ;
let arrayB =
arrayA . map ( double ) ;
console . log ( arrayB ) ;
// [2] let double =
fun a -> a * 2
let listA = [ 1 ]
let listB =
listA |> List.map double
console.log listB
// [2] เราสามารถรับรู้อาร์เรย์ [2] เหมือนกับ เซลล์ และ ค่า 2 ของสเปรดชีต อย่างไรก็ตามสเปรดชีตและ ไทม์ไลน์ รักษาความสัมพันธ์ double เมื่อค่าเปลี่ยนไปตามไทม์ไลน์
Timeline<'a> nextT'a -> Timeline < 'a > -> Timeline < 'a > let timelineA ' =
timelineA |> nextT 3 หรือในกรณีส่วนใหญ่เราไม่ต้องการ timelineA' และต้องการทิ้งมันดังนั้นเพียง ignore ค่าที่ส่งคืน
let timelineA = Timeline 1
timelineA
|> nextT 3
|> ignore
console.log timelineA.lastVal
// 3 let double = fun a -> a * 2
// ① initialize timelineA
let timelineA = Timeline 1
// confirm the lastVal of timelineA
console.log timelineA.lastVal
// 1
// ② the binary operation
let timelineB =
timelineA |> mapT double
// confirm the lastVal of timelineB
console.log timelineB.lastVal
// 2
//=====================================
// ③ update the lastVal of timelineA
timelineA
|> nextT 3
|> ignore
// update to timelineA will trigger
// a reactive update of timelineB
// confirm the lastVal of timelineA & timelineB
console.log timelineA.lastVal
// 3
console.log timelineB.lastVal
// 6 import van from "vanjs-core"
const { button , div , h2 } = van . tags
const Counter =
( ) => {
const counter = van . state ( 0 )
van . derive ( ( ) =>
console . log ( `Counter: ${ counter . val } ` ) )
return div (
h2 ( "❤️ " , counter ) ,
button (
{
onclick : ( ) => ++ counter . val
} ,
"?"
) ,
button (
{
onclick : ( ) => -- counter . val
} ,
"?"
) ,
)
}
van . add ( document . body , Counter ( ) ) module CounterApp
open Browser
open Browser. Types
open Fable. Core . JsInterop
open Van. Basic // import tags, add
open Van. TimelineElement // import Timeline
let div : Tag = tags?div
let h2 : Tag = tags?h2
let icon : Tag = tags? `` md-icon ``
let iconButton : Tag = tags? `` md-icon-button ``
let Counter =
fun _ ->
let counter = Timeline 0 // ① initialize an Timeline
counter // ② the binary operation of the Timeline
|> mapT ( fun value ->
console.log $ " Counter: {value} " )
|> ignore
// ignore the return value of `console.log`
div [
h2 [ " ❤️ " ; counter.el ] // ? `counter.el`
iconButton [ // for Reactive DOM element
{| onclick = fun _ ->
counter // ③ update the Timeline
|> nextT ( counter.lastVal + 1 )
|}
icon [ " thumb_up " ]
]
iconButton [
{| onclick = fun _ ->
counter // ③ update the Timeline
|> nextT ( counter.lastVal - 1 )
|}
icon [ " thumb_down " ]
]
]
add [ document.body ; Counter ()]
|> ignoreการสาธิต
https://codepen.io/kentechgeek/pen/goyqnqb?editors=1111
| สารบัญ |
|---|
| - รถตู้ ความหลากหลายของเทคโนโลยีเว็บ สำหรับการพัฒนาแอพข้ามแพลตฟอร์ม |
| เริ่มต้น |
| ส่วนประกอบของเว็บ |
| ⚡การเขียนโปรแกรมปฏิกิริยาการทำงาน (FRP) การเขียนโปรแกรมที่ใช้งานได้คืออะไร? ไดรฟ์รหัสการเขียนโปรแกรมที่ใช้งานได้อย่างไร |
| timeline |
| ⏱ประเภทที่ไม่มีค่าใช้จ่าย ประเภทโมฆะเป็นโมฆะและตัวเลือกคืออะไร? |
| ⏱ไทม์ไลน์เป็นโมฆะ |
| ⏱งานไทม์ไลน์ |
| ⏱งานไทม์ไลน์ concat |
| ⏱งานไทม์ไลน์หรือ |
| ⏱งานไทม์ไลน์และ |
| การอภิปราย |
ด้วยความสำคัญที่สำคัญของ NULL ในการพัฒนาซอฟต์แวร์ที่ทันสมัยฉันได้ทุ่มเทบทความแยกต่างหากเพื่อสำรวจแนวคิดและประโยชน์หลัก
ประเภทค่าที่เป็นโมฆะใน F#
ค่าที่เป็นโมฆะประเภท
Nullable<'T>แสดงถึงประเภทโครงสร้างใด ๆ ที่อาจเป็นnullสิ่งนี้มีประโยชน์เมื่อมีปฏิสัมพันธ์กับไลบรารีและส่วนประกอบที่อาจเลือกที่จะเป็นตัวแทนของประเภทเหล่านี้เช่นจำนวนเต็มด้วยค่าnullสำหรับเหตุผลที่มีประสิทธิภาพ ประเภทพื้นฐานที่สำรองสิ่งก่อสร้างนี้เป็นระบบ
สามารถแสดงถึงประเภท struct ซึ่งข้อ จำกัด เป็นปัญหา
การใช้ประเภทอ้างอิงที่เป็นโมฆะใน F#
f#: ฉันจะแปลงตัวเลือก <'a> เป็นโมฆะได้อย่างไรเมื่อ' A สามารถเป็น System.string ได้อย่างไร
มันจะดีถ้าเราสามารถเขียน ประเภทที่ไม่มีค่าใช้จ่ายใด ๆ รวมถึงประเภทการอ้างอิง ใน F#
F# RFC FS -1060 - ประเภทอ้างอิงที่เป็นโมฆะ
let nullable1 =
Null
let nullable2 =
NullableT " hello "
log nullable1
// Null
log nullable2
// T hello
log nullable2.Value
// hello ข้อกำหนดนี้คล้ายกับประเภทค่า Nullable Nullable ของ F#แต่ไม่เหมือนกับ NullableT สามารถแสดงประเภทอ้างอิงใด ๆ ได้
F# การสนับสนุน Nullness อาจมาเร็ว ๆ นี้!
ตัวอย่างของงานที่ทำในคอมไพเลอร์ F# เพื่อรองรับความสามารถในการเป็นโมฆะของ. NET
| สารบัญ |
|---|
| - รถตู้ ความหลากหลายของเทคโนโลยีเว็บ สำหรับการพัฒนาแอพข้ามแพลตฟอร์ม |
| เริ่มต้น |
| ส่วนประกอบของเว็บ |
| ⚡การเขียนโปรแกรมปฏิกิริยาการทำงาน (FRP) การเขียนโปรแกรมที่ใช้งานได้คืออะไร? ไดรฟ์รหัสการเขียนโปรแกรมที่ใช้งานได้อย่างไร |
| timeline |
| ⏱ประเภทที่ไม่มีค่าใช้จ่าย ประเภทโมฆะเป็นโมฆะและตัวเลือกคืออะไร? |
| ⏱ไทม์ไลน์เป็นโมฆะ |
| ⏱งานไทม์ไลน์ |
| ⏱งานไทม์ไลน์ concat |
| ⏱งานไทม์ไลน์หรือ |
| ⏱งานไทม์ไลน์และ |
| การอภิปราย |
ด้วยการใช้ ประเภทที่ไม่มีค่าใช้จ่าย เราสามารถให้บริการใหม่ที่จับคู่กับ ไทม์ไลน์
การเริ่มต้น ไทม์ไลน์ ด้วยค่า Null ฟังก์ชั่นที่ให้ไว้ยังคงไม่ได้ดำเนินการและรออยู่ในสถานะที่รอดำเนินการ เมื่อค่า ไทม์ไลน์ ได้รับการอัปเดตเป็นค่าที่ไม่เป็น Null โดยเหตุการณ์ที่ถูกต้องฟังก์ชั่นจะถูกทริกเกอร์และดำเนินการ
Timeline<NullableT<'a>>TimelineNullableT < 'a > -> Timeline < NullableT < 'a >> let timelineNullable = Timeline Null
log timelineNullable.lastVal // use `log` of Timeline
// Nullพิจารณาไทม์ไลน์นี้เป็นเซลล์เปล่าในแอพสเปรดชีต
ประเภท Timeline และฟังก์ชั่น:
①ฟังก์ชั่นเพื่อเริ่มต้น Timeline<'a>
①ฟังก์ชั่นเพื่อเริ่ม Timeline<NullableT<'a>>
เป็น เอนทิตีเดียวกัน
พิจารณา Timeline สามารถยอมรับประเภททั่วไปของ 'a รวมถึง NullableT<'a>
ในอีกทางหนึ่งในกรณีของ Timeline<NullableT<'a>> โดยที่ค่าพารามิเตอร์เป็นประเภทที่เป็นโมฆะหากเราต้องการพฤติกรรม Timeline เพื่อละเว้นฟังก์ชั่นที่ให้ไว้และผ่านค่า Null เมื่อพารามิเตอร์เป็น Null เราสามารถใช้ตัวดำเนินการเฉพาะตามที่แสดงด้านล่าง
mapTN ( NullableT < 'a > -> NullableT < 'b >) -> ( Timeline < NullableT < 'a >> -> Timeline < NullableT < 'b >>)bindTN ( NullableT < 'a > -> Timeline < NullableT < 'b >>) -> ( Timeline < NullableT < 'a >> -> Timeline < NullableT < 'b >>) เมื่อผู้ประกอบการไบนารี: mapT ,
let double =
fun a -> NullableT ( a * 2 )
// ① initialize timelineA
let timelineA = Timeline Null
log timelineA.lastVal // use `log` of Timeline
// Null
// ② the binary operation
let timelineB =
timelineA |> mapTN double
// currently, `timelineA = Timeline Null`
// so, `double` function is ignored
// and `timelineB` value becomes `Null`
log timelineB.lastVal // use `log` of Timeline
// Nullรหัสนี้สำหรับการดำเนินการไบนารีนั้นสอดคล้องกับการใช้งานพื้นฐานของแอพสเปรดชีต
let timelineA ' =
timelineA |> nextTN ( NullableT 3 ) หรือในกรณีส่วนใหญ่เราไม่ต้องการ timelineA' และต้องการทิ้งมันดังนั้นเพียง ignore ค่าที่ส่งคืน
Timeline<'a> let double =
fun a -> NullableT ( a * 2 )
// ① initialize timelineA
let timelineA = Timeline Null
log timelineA.lastVal // use `log` of Timeline
// Null
// ② the binary operation
let timelineB =
timelineA |> mapTN double
// currently, `timelineA = Timeline Null`
// so, `double` function is ignored
// and `timelineB` value becomes `Null`
log timelineB.lastVal // use `log` of Timeline
// Null
// ③ update the lastVal of timelineA
timelineA
|> nextTN ( NullableT 3 )
|> ignore
log timelineA.lastVal // use `log` of Timeline
// T 3
// Now, `timelineA` value is updated to non `Null` value
// Accordingly, `timelineB` reactively becomes `double` of it
log timelineB.lastVal
// T 6 module Number
open Browser
open Browser. Types
open Fable. Core . JsInterop
open Van. Basic // import tags, add
open Van. TimelineElement // import Timeline
open Van. TimelineElementNullable // import Timelinetc.
open Van. Nullable // import NullableT
open Van. TimelineElementTask
let h4 : Tag = tags?h4
let fluentCard : Tag = tags? `` fluent-card ``
let fluentTextField : Tag = tags? `` fluent-text-field ``
let Number =
fun _ ->
let number = Timeline Null
let numberX2 =
number
|> mapTN ( fun n -> NullableT ( n * 2 )) //System.Nullable
fluentCard [
{| `` class `` = " custom1 " |}
h4 [ " Number " ]
fluentTextField [
{|
appearance = " outline "
required = true
`` type `` = " number "
placeholder = " 1 "
oninput =
fun e ->
let value =
if e?target?value = " "
then Null
else NullableT e?target?value
if value = Null // clear the output textField
then numberX2
|> nextTN Null
|> ignore
document.getElementById ( " output-field " )? value
<- " Null " // clear the output textField
else ()
number
|> nextTN value
|> ignore
|}
]
h4 [ " Number × 2 " ]
fluentTextField [
{|
appearance = " outline "
readonly = true
value = numberX2.el
id = " output-field "
|}
]
]
add [ document.body ; Number ()]
|> ignoreการสาธิต
https://codepen.io/kentechgeek/pen/wvznvzj?editors=1111
| สารบัญ |
|---|
| - รถตู้ ความหลากหลายของเทคโนโลยีเว็บ สำหรับการพัฒนาแอพข้ามแพลตฟอร์ม |
| เริ่มต้น |
| ส่วนประกอบของเว็บ |
| ⚡การเขียนโปรแกรมปฏิกิริยาการทำงาน (FRP) การเขียนโปรแกรมที่ใช้งานได้คืออะไร? ไดรฟ์รหัสการเขียนโปรแกรมที่ใช้งานได้อย่างไร |
| timeline |
| ⏱ประเภทที่ไม่มีค่าใช้จ่าย ประเภทโมฆะเป็นโมฆะและตัวเลือกคืออะไร? |
| ⏱ไทม์ไลน์เป็นโมฆะ |
| ⏱งานไทม์ไลน์ |
| ⏱งานไทม์ไลน์ concat |
| ⏱งานไทม์ไลน์หรือ |
| ⏱งานไทม์ไลน์และ |
| การอภิปราย |
ในขณะที่ผู้ให้บริการ ที่เป็นโมฆะไทม์ไลน์ เสนอหลักการพื้นฐานคล้ายกับสัญญาของ JavaScript พวกเขาไม่สามารถจัดการการผูกมัดงานเช่น Promie จากนั้น
ขึ้นอยู่กับ ไทม์ไลน์ที่ไม่มีค่าใช้จ่าย เราสามารถรับ งานไทม์ไลน์ ซึ่งมีความสามารถในการผูกมัดงาน
TaskTimeline < NullableT < 'a >> -> 'b -> unit let task =
fun timelineResult previousResult ->
log " -----------task1 started... "
log previousResult
// delay-------------------------------
let f = fun _ ->
log " .......task1 done "
timelineResult
|> nextTN ( NullableT 1 )
|> ignore
setTimeout f 2000taskTTask < 'a , NullableT < 'a0 >> -> Timeline < NullableT < 'a >> -> Timeline < NullableT < 'a >> let timelineStarter =
Timeline ( NullableT 0 )
// tasks start immediately
timelineStarter
|> taskT task1
|> taskT task2
|> taskT task3
|> ignore| สารบัญ |
|---|
| - รถตู้ ความหลากหลายของเทคโนโลยีเว็บ สำหรับการพัฒนาแอพข้ามแพลตฟอร์ม |
| เริ่มต้น |
| ส่วนประกอบของเว็บ |
| ⚡การเขียนโปรแกรมปฏิกิริยาการทำงาน (FRP) การเขียนโปรแกรมที่ใช้งานได้คืออะไร? ไดรฟ์รหัสการเขียนโปรแกรมที่ใช้งานได้อย่างไร |
| timeline |
| ⏱ประเภทที่ไม่มีค่าใช้จ่าย ประเภทโมฆะเป็นโมฆะและตัวเลือกคืออะไร? |
| ⏱ไทม์ไลน์เป็นโมฆะ |
| ⏱งานไทม์ไลน์ |
| ⏱งานไทม์ไลน์ concat |
| ⏱งานไทม์ไลน์หรือ |
| ⏱งานไทม์ไลน์และ |
| การอภิปราย |
taskConcat หรือ (+>) ( Task -> Task ) -> Task let task12 =
task1 +> task2
let task123 =
task1 +> task2 +> task3
let task1234 =
task123 +> task4 module Tasks
open Browser
open Browser. Types
open Fable. Core . JsInterop
open Van. Basic // import tags, add
open Van. TimelineElement // import Timeline
open Van. TimelineElementNullable // import Timelinetc.
open Van. Nullable // import NullableT
open Van. TimelineElementTask
open Van. TimelineElementTaskConcat
open System. Timers
let setTimeout f delay =
let timer = new Timer ( float delay )
timer.AutoReset <- false
timer.Elapsed.Add ( fun _ -> f ())
timer.Start ()
let br : Tag = tags? `` br ``
let fluentCard : Tag = tags? `` fluent-card ``
let linerProgress : Tag = tags? `` md-linear-progress ``
let Tasks =
fun _ ->
let progressInit = false
let progressStart = true
let progressDone = false
let percentInit = 0.0
let percentStart = 0.0
let percentDone = 1.0
let timelineProgress1 = Timeline progressInit
let timelineProgress2 = Timeline progressInit
let timelineProgress3 = Timeline progressInit
let timelinePercent1 = Timeline percentInit
let timelinePercent2 = Timeline percentInit
let timelinePercent3 = Timeline percentInit
let taskStart =
fun timelineProgress timelinePercent ->
timelineProgress
|> nextT progressStart
|> ignore
timelinePercent
|> nextT percentStart
|> ignore
let taskDone =
fun timelineProgress timelinePercent timelineResult ->
timelineProgress
|> nextT progressDone
|> ignore
timelinePercent
|> nextT percentDone
|> ignore
timelineResult
|> nextTN ( NullableT 999 )
|> ignore
let task1 =
fun timelineResult previousResult ->
log " -----------task1 started... "
taskStart timelineProgress1 timelinePercent1
// delay-------------------------------
let f = fun _ ->
log " ...task1 done "
taskDone timelineProgress1 timelinePercent1 timelineResult
setTimeout f 2500
let task2 =
fun timelineResult previousResult ->
log " -----------task2 started... "
taskStart timelineProgress2 timelinePercent2
// delay-------------------------------
let f = fun _ ->
log " ...task2 done "
taskDone timelineProgress2 timelinePercent2 timelineResult
setTimeout f 2500
let task3 =
fun timelineResult previousResult ->
log " -----------task3 started... "
taskStart timelineProgress3 timelinePercent3
// delay-------------------------------
let f = fun _ ->
log " ...task3 done "
taskDone timelineProgress3 timelinePercent3 timelineResult
setTimeout f 2500
let timelineStarter = Timeline Null //tasks disabled initially
let task123 =
task1 +>
task2 +>
task3
timelineStarter
|> taskT task123
|> ignore
(* task123 can be written as below
timelineStarter
|> taskT task1
|> taskT task2
|> taskT task3
|> ignore
*)
let start =
fun _ -> // timeline will start
timelineStarter
|> nextTN ( NullableT 0 )
|> ignore
setTimeout start 2000
fluentCard [
{| `` class `` = " custom2 " |}
br []
linerProgress [
{| indeterminate = timelineProgress1.el
value = timelinePercent1.el |}
]
br []
linerProgress [
{| indeterminate = timelineProgress2.el
value = timelinePercent2.el |}
]
br []
linerProgress [
{| indeterminate = timelineProgress3.el
value = timelinePercent3.el |}
]
]
add [ document.body ; Tasks ()]
|> ignoreการสาธิต
https://codepen.io/kentechgeek/pen/jordjvy?editors=1111
module Tasks
open Van. TimelineElement // import Timeline
open Van. TimelineElementNullable // import Timelinetc.
open Van. Nullable // import NullableT
open Van. TimelineElementTask
open Van. TimelineElementTaskConcat
open System. Timers
let setTimeout f delay =
let timer = new Timer ( float delay )
timer.AutoReset <- false
timer.Elapsed.Add ( fun _ -> f ())
timer.Start ()
let nonNull = NullableT true // some non-null value
let task1 =
fun timelineResult previousResult ->
log " -----------task1 started... "
// delay-------------------------------
let f = fun _ ->
log " ...task1 done "
timelineResult
|> nextTN nonNull
|> ignore
setTimeout f 2500
let task2 =
fun timelineResult previousResult ->
log " -----------task2 started... "
// delay-------------------------------
let f = fun _ ->
log " ...task2 done "
timelineResult
|> nextTN nonNull
|> ignore
setTimeout f 1000
let task3 =
fun timelineResult previousResult ->
log " -----------task3 started... "
// delay-------------------------------
let f = fun _ ->
log " ...task3 done "
timelineResult
|> nextTN nonNull
|> ignore
setTimeout f 3000
let timelineStarter = Timeline Null //tasks disabled initially
let task123 =
task1 +>
task2 +>
task3
timelineStarter
|> taskT task123
|> ignore
(* task123 can be written as below
timelineStarter
|> taskT task1
|> taskT task2
|> taskT task3
|> ignore
*)
let start =
fun _ -> // timeline will start
timelineStarter
|> nextTN nonNull
|> ignore
setTimeout start 2000
การสาธิต
https://codepen.io/kentechgeek/pen/baeeyvl?editors=1111
| สารบัญ |
|---|
| - รถตู้ ความหลากหลายของเทคโนโลยีเว็บ สำหรับการพัฒนาแอพข้ามแพลตฟอร์ม |
| เริ่มต้น |
| ส่วนประกอบของเว็บ |
| ⚡การเขียนโปรแกรมปฏิกิริยาการทำงาน (FRP) การเขียนโปรแกรมที่ใช้งานได้คืออะไร? ไดรฟ์รหัสการเขียนโปรแกรมที่ใช้งานได้อย่างไร |
| timeline |
| ⏱ประเภทที่ไม่มีค่าใช้จ่าย ประเภทโมฆะเป็นโมฆะและตัวเลือกคืออะไร? |
| ⏱ไทม์ไลน์เป็นโมฆะ |
| ⏱งานไทม์ไลน์ |
| ⏱งานไทม์ไลน์ concat |
| ⏱งานไทม์ไลน์หรือ |
| ⏱งานไทม์ไลน์และ |
| การอภิปราย |
taskOr หรือ (+|) ( Task -> Task ) -> Task let task12 =
task1 +| task2
let task123 =
task1 +| task2 +| task3
let task1234 =
task123 +| task4 module TaskOr
open Van. TimelineElement // import Timeline
open Van. TimelineElementNullable // import Timelinetc.
open Van. Nullable // import NullableT
open Van. TimelineElementTask
open Van. TimelineElementTaskOr
open System. Timers
let setTimeout f delay =
let timer = new Timer ( float delay )
timer.AutoReset <- false
timer.Elapsed.Add ( fun _ -> f ())
timer.Start ()
let nonNull = NullableT true
let task1 =
fun timelineResult previousResult ->
log " -----------task1 started... "
// delay-------------------------------
let f = fun _ ->
log " ...task1 done "
timelineResult
|> nextTN ( NullableT " task1 " )
|> ignore
setTimeout f 2500
let task2 =
fun timelineResult previousResult ->
log " -----------task2 started... "
// delay-------------------------------
let f = fun _ ->
log " ...task2 done "
timelineResult
|> nextTN ( NullableT " task2 " )
|> ignore
setTimeout f 1000
let task3 =
fun timelineResult previousResult ->
log " -----------task3 started... "
// delay-------------------------------
let f = fun _ ->
log " ...task3 done "
timelineResult
|> nextTN ( NullableT " task3 " )
|> ignore
setTimeout f 3000
let timelineStarter = Timeline Null //tasks disabled initially
let task123 =
task1 +| task2 +| task3
let taskOutput =
fun timelineResult ( previousResult : NullableT < string >)
-> log ( " The fastest result from: "
+ previousResult.Value )
timelineStarter
|> taskT task123 // Run all tasks then return the fastest result
|> taskT taskOutput // log the fastest result
|> ignore
let start =
fun _ -> // timeline will start
timelineStarter
|> nextTN nonNull
|> ignore
setTimeout start 2000
การสาธิต
https://codepen.io/kentechgeek/pen/zyxqgwq?editors=1111
| สารบัญ |
|---|
| - รถตู้ ความหลากหลายของเทคโนโลยีเว็บ สำหรับการพัฒนาแอพข้ามแพลตฟอร์ม |
| เริ่มต้น |
| ส่วนประกอบของเว็บ |
| ⚡การเขียนโปรแกรมปฏิกิริยาการทำงาน (FRP) การเขียนโปรแกรมที่ใช้งานได้คืออะไร? ไดรฟ์รหัสการเขียนโปรแกรมที่ใช้งานได้อย่างไร |
| timeline |
| ⏱ประเภทที่ไม่มีค่าใช้จ่าย ประเภทโมฆะเป็นโมฆะและตัวเลือกคืออะไร? |
| ⏱ไทม์ไลน์เป็นโมฆะ |
| ⏱งานไทม์ไลน์ |
| ⏱งานไทม์ไลน์ concat |
| ⏱งานไทม์ไลน์หรือ |
| ⏱งานไทม์ไลน์และ |
| การอภิปราย |
taskAnd และ (+&) ( Task -> Task ) -> Task let task12 =
task1 +& task2
let task123 =
task1 +& task2 +& task3
let task1234 =
task123 +& task4 module TaskAnd
open Van. TimelineElement // import Timeline
open Van. TimelineElementNullable // import Timelinetc.
open Van. Nullable // import NullableT
open Van. TimelineElementTask
open Van. TimelineElementTaskAnd
open System. Timers
let setTimeout f delay =
let timer = new Timer ( float delay )
timer.AutoReset <- false
timer.Elapsed.Add ( fun _ -> f ())
timer.Start ()
let nonNull = NullableT true
let task1 =
fun timelineResult previousResult ->
log " -----------task1 started... "
// delay-------------------------------
let f = fun _ ->
log " ...task1 done "
timelineResult
|> nextTN ( NullableT " task1 " )
|> ignore
setTimeout f 2500
let task2 =
fun timelineResult previousResult ->
log " -----------task2 started... "
// delay-------------------------------
let f = fun _ ->
log " ...task2 done "
timelineResult
|> nextTN ( NullableT " task2 " )
|> ignore
setTimeout f 1000
let task3 =
fun timelineResult previousResult ->
log " -----------task3 started... "
// delay-------------------------------
let f = fun _ ->
log " ...task3 done "
timelineResult
|> nextTN ( NullableT " task3 " )
|> ignore
setTimeout f 3000
let timelineStarter = Timeline Null //tasks disabled initially
let task123 =
task1 +& task2 +& task3
let taskOutput =
fun timelineResult ( previousResult : NullableT < ListResult < 'a >>)
-> log previousResult.Value.results
timelineStarter
|> taskT task123 // Run all tasks then return the list of results
|> taskT taskOutput // log the list of results
|> ignore
let start =
fun _ -> // timeline will start
timelineStarter
|> nextTN nonNull
|> ignore
setTimeout start 2000
การสาธิต
https://codepen.io/kentechgeek/pen/pobmjzq?editors=1111