สิ่งใดที่คุณเรียกใช้ฟังก์ชันที่อินพุตเดียวกันจะส่งคืนเอาต์พุตเดียวกันเสมอ แต่ก็มีผลข้างเคียงเช่นกัน


43

สมมติว่าเรามีฟังก์ชั่นบริสุทธิ์ปกติเช่น

function add(a, b) {
  return a + b
}

จากนั้นเราก็ดัดแปลงมันโดยที่มันมีผลข้างเคียง

function add(a, b) {
  writeToDatabase(Math.random())
  return a + b;
}

มันไม่ถือว่าเป็นฟังก์ชั่นที่บริสุทธิ์เท่าที่ฉันรู้เพราะฉันมักจะได้ยินคนเรียกฟังก์ชั่นที่บริสุทธิ์ว่า "ฟังก์ชั่นที่ไม่มีผลข้างเคียง" อย่างไรก็ตามมันจะทำตัวเหมือนฟังก์ชั่นแท้ๆเท่าที่ความจริงที่ว่ามันจะคืนค่าเอาต์พุตเดียวกันสำหรับอินพุตเดียวกัน

มีชื่อที่แตกต่างกันสำหรับฟังก์ชั่นประเภทนี้มันไม่มีชื่อหรือมันยังบริสุทธิ์อยู่และฉันเข้าใจผิดเกี่ยวกับคำนิยามของความบริสุทธิ์หรือไม่?


91
"ไม่ใช่ฟังก์ชั่นที่บริสุทธิ์"
Ross Patterson

2
@ RossPatterson เป็นสิ่งที่ฉันคิดเช่นกัน แต่โดยการถามฉันเรียนรู้เกี่ยวกับความโปร่งใสในการอ้างอิงดังนั้นฉันดีใจที่ฉันไม่ได้เก็บมันไว้กับตัวเอง
m0meni

9
หากwriteToDatabaseล้มเหลวอาจทำให้เกิดข้อยกเว้นทำให้addฟังก์ชันที่สองของคุณสร้างข้อยกเว้นบางครั้งแม้ว่าถูกเรียกด้วยอาร์กิวเมนต์เดียวกันที่ก่อนหน้านี้ไม่มีปัญหา ... ส่วนใหญ่ที่มีผลข้างเคียงแนะนำเงื่อนไขที่เกี่ยวข้องกับข้อผิดพลาดชนิดนี้ "ความบริสุทธิ์อินพุต - เอาท์พุต"
Bakuriu

25
สิ่งที่ให้เอาต์พุตเดียวกันสำหรับอินพุตที่กำหนดไว้เสมอเรียกว่าdeterministic
njzk2

2
@ njzk2: จริง แต่ก็ไร้สัญชาติด้วย กำหนด statefulฟังก์ชั่นไม่อาจให้ผลลัพธ์ที่เหมือนกันสำหรับทุกการป้อนข้อมูล ตัวอย่าง: F(x)ถูกกำหนดให้ส่งคืนtrueหากถูกเรียกด้วยอาร์กิวเมนต์เดียวกันกับการโทรก่อนหน้า เห็นได้ชัดว่ามีลำดับที่{1,2,2} => {undefined, false, true}กำหนดไว้ แต่ก็ให้ผลลัพธ์ที่แตกต่างกันF(2)ไป
MSalters

คำตอบ:


85

ฉันไม่แน่ใจเกี่ยวกับคำจำกัดความสากลของความบริสุทธิ์ แต่จากมุมมองของ Haskell (ภาษาที่โปรแกรมเมอร์มักสนใจเกี่ยวกับสิ่งต่าง ๆ เช่นความบริสุทธิ์และความโปร่งใสในการอ้างอิง) เฉพาะหน้าที่แรกของคุณคือ "บริสุทธิ์" รุ่นที่สองของaddไม่บริสุทธิ์ ดังนั้นเพื่อตอบคำถามของคุณฉันจะเรียกมันว่า "ไม่บริสุทธิ์";)

ตามคำนิยามนี้ฟังก์ชั่นแท้เป็นฟังก์ชั่นที่:

  1. ขึ้นอยู่กับอินพุตเท่านั้น นั่นคือเมื่อได้รับอินพุตเดียวกันมันจะส่งคืนเอาต์พุตเดิมเสมอ
  2. มีความโปร่งใสในการอ้างอิง: ฟังก์ชันสามารถแทนที่ได้อย่างอิสระด้วยค่าของมันและ "พฤติกรรม" ของโปรแกรมจะไม่เปลี่ยนแปลง

ด้วยคำจำกัดความนี้มันชัดเจนว่าฟังก์ชั่นที่สองของคุณไม่สามารถถูกพิจารณาว่าบริสุทธิ์ได้เนื่องจากมันแบ่งกฎ 2 นั่นคือสองโปรแกรมต่อไปนี้ไม่เทียบเท่า:

function f(a, b) { 
    return add(a, b) + add(a, b);
}

และ

function g(a, b) {
    c = add(a, b);
    return c + c;
}

นี่เป็นเพราะแม้ว่าทั้งสองฟังก์ชั่นจะคืนค่าเดิม แต่ฟังก์ชั่นfจะเขียนไปยังฐานข้อมูลสองครั้ง แต่gจะเขียนครั้งเดียว มีโอกาสมากที่การเขียนลงในฐานข้อมูลเป็นส่วนหนึ่งของพฤติกรรมที่สังเกตได้ของโปรแกรมของคุณซึ่งในกรณีนี้ฉันได้แสดงเวอร์ชันที่สองของคุณaddไม่ใช่ "บริสุทธิ์"

หากการเขียนไปยังฐานข้อมูลนั้นไม่ใช่ส่วนที่สังเกตได้จากพฤติกรรมของโปรแกรมของคุณดังนั้นทั้งสองเวอร์ชันaddจะถือว่าเทียบเท่าและบริสุทธิ์ แต่ฉันไม่สามารถนึกถึงสถานการณ์ที่การเขียนไปยังฐานข้อมูลไม่สำคัญ แม้กระทั่งเรื่องการเข้าสู่ระบบ!


1
ไม่เพียง "ขึ้นอยู่กับการป้อนข้อมูล" ซ้ำซ้อนที่ได้รับอ้างอิงโปร่งใส ซึ่งหมายความว่า RT มีความหมายเหมือนกันกับความบริสุทธิ์ (ฉันสับสนมากขึ้นเกี่ยวกับแหล่งข้อมูลนี้ที่ฉันค้นหามากขึ้น)
Ixrec

ฉันเห็นว่ามันสับสน ฉันสามารถคิดถึงตัวอย่างที่วางแผนไว้เท่านั้น กล่าวว่าf(x)ขึ้นอยู่ไม่เพียงแต่ยังอยู่ในตัวแปรทั่วโลกบางภายนอกx yแล้วถ้าfมีทรัพย์สินของ RT ที่คุณได้อย่างอิสระสามารถสลับเกิดขึ้นทั้งหมดกับค่าตอบแทนของมันตราบใดที่คุณไม่ได้สัมผัส yใช่ตัวอย่างของฉันไม่แน่ใจ แต่สิ่งที่สำคัญคือถ้าfเขียนไปยังฐานข้อมูล (หรือเขียนลงในบันทึก) มันจะสูญเสียคุณสมบัติของ RT: ตอนนี้ไม่สำคัญว่าคุณจะออกจากโลกที่yไม่มีใครแตะต้องคุณรู้ว่าความหมายของโปรแกรมของคุณเปลี่ยนแปลงขึ้นอยู่กับว่าคุณจริงหรือไม่ โทรfหรือเพียงแค่ใช้ค่าส่งคืน
Andres F.

ฮึ. ให้เราบอกว่าเรามีฟังก์ชั่นที่บริสุทธิ์ยกเว้นผลข้างเคียงและยังรับประกันว่าจะมีพฤติกรรมดังกล่าวที่ตัวอย่างสองตัวอย่างของคุณเทียบเท่า (ฉันมีกรณีนี้เกิดขึ้นจริง ๆ แล้วมันไม่ใช่สมมุติฐาน) ฉันคิดว่าเรายังไม่ได้ทำ
Joshua

2
ฉันจะโต้แย้งว่าฟังก์ชั่นที่สองสามารถทำลายกฎ # 1 ด้วย ขึ้นอยู่กับภาษาและแนวทางการจัดการข้อผิดพลาดของ API ฐานข้อมูลที่ใช้งานฟังก์ชันอาจไม่ส่งคืนสิ่งใดเลยหากฐานข้อมูลไม่พร้อมใช้งานหรือการเขียน db ล้มเหลวด้วยเหตุผลบางประการ
Zach Lipton

1
ตั้งแต่ Haskell ถูกกล่าวถึง: ใน Haskell เพิ่มผลข้างเคียงเช่นที่ต้องเปลี่ยนลายเซ็นของฟังก์ชั่น (คิดว่ามันเหมือนกับการให้ฐานข้อมูลต้นฉบับเป็นอินพุตเพิ่มเติมและรับฐานข้อมูลที่แก้ไขแล้วเป็นค่าตอบแทนเพิ่มเติมของฟังก์ชัน) ในความเป็นจริงแล้วมันเป็นไปได้ที่จะสร้างแบบจำลองผลข้างเคียงที่ค่อนข้างหรูหราในระบบพิมพ์แบบนั้นมันเป็นเพียงว่าภาษากระแสหลักในปัจจุบันไม่สนใจผลข้างเคียงและความบริสุทธิ์เพียงพอที่จะทำสิ่งนี้
ComicSansMS

19

สิ่งใดที่คุณเรียกใช้ฟังก์ชัน [ซึ่ง] อินพุตเดียวกันจะส่งคืนเอาต์พุตเดียวกันเสมอ แต่ก็มีผลข้างเคียงเช่นกัน

ฟังก์ชั่นดังกล่าวเรียกว่า

กำหนด

อัลกอริทึมที่มีพฤติกรรมที่สามารถทำนายได้อย่างสมบูรณ์จากอินพุต

termwiki.com

เกี่ยวกับรัฐ:

ฟังก์ชั่นไม่มีสถานะขึ้นอยู่กับคำจำกัดความของฟังก์ชั่นที่คุณใช้ หากคุณมาจากโลกแห่งวัตถุที่มุ่งเน้นจำไว้ว่าx.f(y)เป็นวิธีการ f(x,y)ในฐานะที่เป็นฟังก์ชั่นมันจะมีลักษณะ และถ้าคุณเข้าสู่การปิดด้วยขอบเขตคำศัพท์ที่ล้อมรอบโปรดจำไว้ว่าสถานะที่ไม่เปลี่ยนรูปอาจจะเป็นส่วนหนึ่งของการแสดงออกของฟังก์ชั่น เป็นเพียงสถานะที่ไม่แน่นอนที่จะส่งผลกระทบต่อฟังก์ชันที่กำหนดขึ้น ดังนั้น f (x) = x + 1 เป็นตัวกำหนดตราบใดที่ 1 ไม่เปลี่ยนแปลง ไม่สำคัญว่าจะเก็บ 1 ไว้ที่ไหน

ฟังก์ชั่นของคุณมีทั้งที่กำหนดขึ้นเอง ครั้งแรกของคุณยังเป็นฟังก์ชั่นที่บริสุทธิ์ ที่สองของคุณไม่บริสุทธิ์

ฟังก์ชั่นบริสุทธิ์

  1. ฟังก์ชันจะประเมินค่าผลลัพธ์เดียวกันเสมอซึ่งให้ค่าอาร์กิวเมนต์ที่เหมือนกันเสมอ ค่าผลลัพธ์ของฟังก์ชั่นไม่สามารถขึ้นอยู่กับข้อมูลหรือสถานะใด ๆ ที่ซ่อนอยู่ซึ่งอาจเปลี่ยนแปลงได้ในขณะที่การดำเนินการของโปรแกรมดำเนินไปหรือระหว่างการดำเนินการต่าง ๆ ของโปรแกรมและไม่สามารถขึ้นอยู่กับอินพุตภายนอกจากอุปกรณ์ I / O

  2. การประเมินผลลัพธ์ไม่ทำให้เกิดผลข้างเคียงหรือเอาท์พุทที่สามารถสังเกตเห็นได้ทางความหมายเช่นการกลายพันธุ์ของวัตถุที่ไม่แน่นอนหรือเอาท์พุทไปยังอุปกรณ์ I / O

wikipedia.org

จุดที่ 1 หมายถึงกำหนดขึ้น จุดที่ 2 หมายถึงความโปร่งใสอ้างอิง พวกเขาช่วยกันหมายถึงฟังก์ชั่นที่บริสุทธิ์อนุญาตให้มีการขัดแย้งเท่านั้นและค่าที่ส่งคืนเพื่อเปลี่ยน ไม่มีอะไรทำให้เกิดการเปลี่ยนแปลง ไม่มีอะไรเปลี่ยนแปลง


-1 การเขียนไปยังฐานข้อมูลขึ้นอยู่กับสถานะภายนอกที่โดยทั่วไปไม่สามารถระบุได้ว่ามองหาอินพุตหรือไม่ ฐานข้อมูลอาจไม่พร้อมใช้งานด้วยเหตุผลหลายประการและการดำเนินการจะสำเร็จหรือไม่นั้นไม่สามารถคาดเดาได้ นี่ไม่ใช่พฤติกรรมที่กำหนดไว้แล้ว
Frax

@Frax หน่วยความจำระบบอาจไม่สามารถใช้งานได้ CPU อาจไม่พร้อมใช้งาน การเป็นคนกำหนดไม่ได้รับประกันความสำเร็จ มันรับประกันได้ว่าพฤติกรรมที่ประสบความสำเร็จสามารถทำนายได้
candied_orange

OOMing ไม่ได้มีเฉพาะฟังก์ชันใด ๆ แต่เป็นประเภทของปัญหาที่แตกต่างกัน ตอนนี้เรามาดูจุดที่ 1 ของคำนิยาม "ฟังก์ชั่นแท้" ของคุณ (ซึ่งหมายถึง "กำหนดขึ้นเอง"): "ค่าผลลัพธ์ของฟังก์ชั่นไม่สามารถขึ้นอยู่กับข้อมูลหรือสถานะใด ๆ ที่ซ่อนอยู่ซึ่งอาจเปลี่ยนแปลงได้ โปรแกรมและไม่สามารถขึ้นอยู่กับอินพุตภายนอกจากอุปกรณ์ I / O " ฐานข้อมูลเป็นสถานะที่ใจดีดังนั้นฟังก์ชั่น OPs จึงไม่ตรงตามเงื่อนไขนี้ - มันไม่ได้กำหนดไว้ล่วงหน้า
Frax

@candied_orange ฉันจะเห็นด้วยถ้าการเขียนไปยังฐานข้อมูลขึ้นอยู่กับอินพุตเท่านั้น Math.random()แต่มันเป็น ดังนั้นไม่เว้นแต่เราจะถือว่า PRNG (แทนที่จะเป็น RNG ทางกายภาพ) และพิจารณาว่า PRNGs ระบุส่วนของอินพุต (ซึ่งไม่ใช่การอ้างอิงคือฮาร์ดโค้ด) มันไม่ได้กำหนดไว้
marstato

1
@candied_orange การอ้างอิงสถานะที่กำหนดของคุณ "อัลกอริทึมที่สามารถทำนายพฤติกรรมได้อย่างสมบูรณ์จากอินพุต" การเขียนถึงฉันสำหรับฉันนั้นเป็นพฤติกรรมที่แน่นอนไม่ใช่ผลลัพธ์
marstato

9

หากคุณไม่สนใจผลข้างเคียงมันก็จะโปร่งใส แน่นอนว่าเป็นไปได้ที่คุณไม่สนใจ แต่มีคนอื่นทำดังนั้นการบังคับใช้ของคำจึงขึ้นอยู่กับบริบท

ผมไม่ทราบว่าของคำทั่วไปสำหรับแม่นยำคุณสมบัติที่คุณอธิบาย แต่เซตที่สำคัญคือผู้ที่มีความidempotent ในวิทยาการคอมพิวเตอร์แตกต่างกันเล็กน้อยในวิชาคณิตศาสตร์ * ฟังก์ชัน idempotentเป็นฟังก์ชันที่สามารถทำซ้ำได้ด้วยเอฟเฟกต์เดียวกัน กล่าวคือผลของผลข้างเคียงของการทำหลายครั้งเหมือนกันกับการทำครั้งเดียว

ดังนั้นหากผลข้างเคียงของคุณคือการอัพเดทฐานข้อมูลด้วยค่าบางอย่างในแถวหนึ่งหรือสร้างไฟล์ที่มีเนื้อหาที่สอดคล้องกันแน่นอนมันจะเป็นidempotentแต่ถ้ามันเพิ่มลงในฐานข้อมูลหรือผนวกเข้ากับไฟล์ แล้วมันจะไม่

การรวมกันของฟังก์ชั่น idempotent อาจหรืออาจจะไม่รวม idempotent

* การใช้idempotentแตกต่างกันในด้านวิทยาศาสตร์คอมพิวเตอร์มากกว่าคณิตศาสตร์ดูเหมือนว่ามาจากการใช้คำศัพท์ทางคณิตศาสตร์ที่ไม่ถูกต้องซึ่งนำมาใช้เพราะแนวคิดนี้มีประโยชน์


3
คำว่า "referential transparent" มีการกำหนดไว้อย่างเข้มงวดมากกว่าคำว่า "ใครสนใจ" แม้ว่าเราจะไม่สนใจปัญหา IO เช่นปัญหาการเชื่อมต่อที่หายไปสตริงการเชื่อมต่อ, หมดเวลา ฯลฯ จากนั้นก็ยังคงเป็นเรื่องง่ายที่จะแสดงให้เห็นว่าโปรแกรมที่แทนที่(f x, f x)ด้วยlet y = f x in (y, y)จะทำงานในออกจากดิสก์พื้นที่ยกเว้นสองครั้งที่รวดเร็วคุณสามารถยืนยันว่าสิ่งเหล่านี้ กรณีขอบคุณไม่สนใจ แต่ด้วยคำจำกัดความที่คลุมเครือเราอาจจะเรียกว่าnew Random().Next()referential โปร่งใสเพราะ heck ฉันไม่สนใจว่าฉันจะได้รับหมายเลขใด
sara

@kai: ขึ้นอยู่กับบริบทคุณอาจละเว้นผลข้างเคียง ในทางกลับกันค่าส่งคืนของฟังก์ชั่นแบบสุ่มไม่ได้เป็นผลข้างเคียง: มันเป็นผลกระทบหลัก
Giorgio

@Giorgio Random.Nextใน. NET มีผลข้างเคียงแน่นอน เป็นอย่างมาก หากคุณสามารถNextกำหนดให้ตัวแปรแล้วโทรNextอีกครั้งและกำหนดให้กับตัวแปรอื่นโอกาสที่พวกเขาจะไม่เท่ากัน ทำไม? เนื่องจากการเรียกNextเปลี่ยนสถานะภายในที่ซ่อนอยู่บางอย่างในRandomวัตถุ นี่คือขั้วตรงข้ามของความโปร่งใสในการอ้างอิง ฉันไม่เข้าใจการอ้างสิทธิ์ของคุณว่า "ผลกระทบหลัก" ไม่สามารถเป็นผลข้างเคียงได้ ในรหัสที่จำเป็นมันเป็นเรื่องธรรมดามากกว่าไม่ใช่ว่าผลกระทบหลักคือผลข้างเคียงเพราะโปรแกรมที่จำเป็นนั้นมีสภาวะเป็นธรรมชาติ
ร่า

3

ฉันไม่ทราบว่าฟังก์ชั่นดังกล่าวเรียกว่า (หรือแม้กระทั่งมีชื่อระบบบางส่วน) แต่ฉันจะเรียกใช้ฟังก์ชันที่ไม่บริสุทธิ์ (เช่นคำตอบอื่น ๆ cowered) แต่จะส่งกลับผลลัพธ์เดียวกันเสมอหากมีพารามิเตอร์เดียวกัน "ฟังก์ชันของมัน พารามิเตอร์ "(เปรียบเทียบกับฟังก์ชั่นของพารามิเตอร์และสถานะอื่น ๆ ) ฉันเรียกมันว่าฟังก์ชั่น แต่น่าเสียดายที่เมื่อเราพูดว่า "ฟังก์ชั่น" ในบริบทของการเขียนโปรแกรมเราหมายถึงสิ่งที่ไม่จำเป็นต้องเป็นฟังก์ชั่นที่แท้จริงเลย


1
ตกลงกัน! มันคือนิยามทางคณิตศาสตร์ของ "ฟังก์ชั่น" (อย่างไม่เป็นทางการ) แต่อย่างที่คุณบอกว่า "ฟังก์ชั่น" น่าเสียดายที่หมายถึงบางสิ่งที่แตกต่างกันในภาษาการเขียนโปรแกรม
Andres F.

2

มันขึ้นอยู่กับว่าคุณใส่ใจเรื่องความไม่บริสุทธิ์หรือไม่ หากความหมายของตารางนี้เป็นสิ่งที่คุณไม่สนใจว่ามีอยู่กี่รายการก็ถือว่าบริสุทธิ์ อื่นมันไม่บริสุทธิ์

หรือหากจะกล่าวอีกวิธีหนึ่งก็เป็นเรื่องดีตราบใดที่การปรับให้เหมาะสมตามความบริสุทธิ์ไม่ทำให้ซีแมนทิกส์ผิดเพี้ยนไป

ตัวอย่างที่เป็นจริงมากขึ้นจะเป็นถ้าคุณพยายามที่จะแก้ปัญหาฟังก์ชั่นนี้และเพิ่มงบการบันทึก ในทางเทคนิคการบันทึกเป็นผลข้างเคียง บันทึกทำให้มันไม่บริสุทธิ์หรือไม่ เลขที่


มันขึ้นอยู่กับ บางทีบันทึกอาจไม่ถูกต้องตัวอย่างเช่นหากคุณสนใจว่ามีกี่ครั้งและในเวลาใดจะมี "INFO f () ชื่อ" ปรากฏในบันทึกของคุณ ซึ่งคุณมักจะทำ :)
Andres F.

8
-1 บันทึกมีความสำคัญ บนแพลตฟอร์มส่วนใหญ่เอาท์พุทใด ๆ โดยนัยประสานกระทู้การดำเนินการ ลักษณะการทำงานของโปรแกรมของคุณจะขึ้นอยู่กับการเขียนเธรดอื่น ๆ , ในตัวเขียนบันทึกภายนอก, บางครั้งการอ่านบันทึก, สถานะของตัวอธิบายไฟล์ มันบริสุทธิ์เหมือนถังดิน
Basilevs

@AndresF คุณอาจไม่สนใจจำนวนครั้งที่แท้จริง คุณอาจสนใจว่ามีการบันทึกหลายครั้งตามที่มีการเรียกใช้ฟังก์ชัน
DeadMG

@Basilevs พฤติกรรมของฟังก์ชั่นไม่ได้ขึ้นอยู่กับพวกเขาเลย หากบันทึกการเขียนล้มเหลวคุณเพียงแค่ดำเนินการต่อ
DeadMG

2
มันเป็นเรื่องของการที่คุณเลือกที่จะกำหนดคนตัดไม้ที่จะเป็นส่วนหนึ่งของสภาพแวดล้อมการดำเนินการหรือไม่ สำหรับตัวอย่างอื่นฟังก์ชั่น pure ของฉันยังคงบริสุทธิ์อยู่หรือไม่ถ้าฉันแนบ debugger เข้ากับกระบวนการและตั้งจุดพักไว้? จากมุมมองของบุคคลที่ใช้ดีบักเกอร์ฟังก์ชั่นนั้นมีผลข้างเคียงอย่างชัดเจน แต่โดยปกติเราจะวิเคราะห์โปรแกรมด้วยหลักการที่ว่า "ไม่นับ" เดียวกันสามารถ (แต่ไม่จำเป็น) ไปสำหรับการบันทึกที่ใช้สำหรับการดีบักซึ่งฉันคิดว่าเป็นสาเหตุที่ร่องรอยซ่อนความไม่บริสุทธิ์ แน่นอนว่าการบันทึกที่สำคัญเช่นสำหรับการตรวจสอบนั้นเป็นผลข้างเคียงที่สำคัญ
Steve Jessop

1

ฉันจะบอกว่าสิ่งที่ดีที่สุดที่จะถามไม่ใช่วิธีที่เราจะเรียกมันว่า แต่วิธีที่เราจะวิเคราะห์ชิ้นส่วนของรหัสดังกล่าว และคำถามสำคัญแรกของฉันในการวิเคราะห์เช่นนี้จะเป็น:

  • ผลข้างเคียงขึ้นอยู่กับอาร์กิวเมนต์ของฟังก์ชันหรือผลลัพธ์ที่เกิดจากผลข้างเคียงหรือไม่?
    • ไม่: "ฟังก์ชั่น effectful" สามารถ refactored เป็นฟังก์ชั่นบริสุทธิ์การกระทำที่มีประสิทธิภาพและกลไกสำหรับการรวมพวกเขา
    • ใช่: "ฟังก์ชั่น effectful" เป็นฟังก์ชั่นที่สร้างผลลัพธ์แบบ monadic

ตรงไปตรงมาเพื่อแสดงใน Haskell (และประโยคนี้เป็นเรื่องตลกเพียงครึ่งเดียว) ตัวอย่างของกรณี "ไม่" จะเป็นดังนี้:

double :: Num a => a -> IO a
double x = do
  putStrLn "I'm doubling some number"
  return (x*2)

ในตัวอย่างนี้การกระทำที่เราดำเนินการ (พิมพ์บรรทัด"I'm doubling some number") ไม่มีผลกระทบต่อความสัมพันธ์ระหว่างxและผลลัพธ์ นี่หมายความว่าเราสามารถ refactor ด้วยวิธีนี้ (โดยใช้Applicativeคลาสและ*>โอเปอเรเตอร์) ซึ่งแสดงให้เห็นว่าฟังก์ชันและเอฟเฟกต์เป็นจริง orthogonal:

double :: Num a => a -> IO a
double x = action *> pure (function x)
  where
    -- The pure function 
    function x = x*2  
    -- The side effect
    action = putStrLn "I'm doubling some number"

ดังนั้นในกรณีนี้ฉันโดยส่วนตัวจะบอกว่ามันเป็นกรณีที่คุณสามารถแยกการทำงานที่บริสุทธิ์ การเขียนโปรแกรม Haskell มากมายเกี่ยวกับสิ่งนี้ - การเรียนรู้วิธีแยกส่วนที่บริสุทธิ์ออกจากโค้ดที่มีประสิทธิภาพ

ตัวอย่างของการเรียงลำดับ "ใช่" โดยที่ส่วนที่บริสุทธิ์และมีประสิทธิภาพไม่ได้เป็นฉากฉาก:

double :: Num a => a -> IO a
double x = do
  putStrLn ("I'm doubling the number " ++ show x)
  return (x*2)

xตอนนี้สตริงที่คุณพิมพ์ขึ้นอยู่กับมูลค่าของ อย่างไรก็ตามส่วนของฟังก์ชั่น (คูณxสอง) ไม่ได้ขึ้นอยู่กับเอฟเฟกต์ทั้งหมดดังนั้นเราจึงยังสามารถแยกมันออกมาได้:

logged :: (a -> b) -> (a -> IO x) -> IO b
logged function logger a = do
  logger a
  return (function a)

double x = logged function logger
  where function = (*2) 
        logger x putStrLn ("I'm doubling the number " ++ show x)

ฉันสามารถสะกดคำจากตัวอย่างอื่น ๆ ได้ แต่ฉันหวังว่านี่จะเพียงพอที่จะแสดงให้เห็นถึงจุดที่ฉันเริ่มต้นด้วย: คุณไม่ได้ "เรียก" มันเป็นบางสิ่งคุณวิเคราะห์ว่าชิ้นส่วนที่บริสุทธิ์และมีประสิทธิภาพเกี่ยวข้องกันอย่างไร เพื่อประโยชน์ของคุณ

นี่คือหนึ่งในเหตุผลที่ Haskell ใช้Monadคลาสนี้อย่างกว้างขวาง Monads เป็นเครื่องมือในการวิเคราะห์และจัดโครงสร้างใหม่


-2

ฟังก์ชั่นที่มีวัตถุประสงค์เพื่อก่อให้เกิดผลข้างเคียงที่มักจะเรียกว่าeffectful ตัวอย่างhttps://slpopejoy.github.io/posts/Effectful01.html


ตอบเท่านั้นที่จะพูดถึงคำที่รู้จักกันอย่างกว้างขวางมีผลบังคับใช้และมันได้รับการโหวตลงคะแนน .... ความไม่รู้เป็นความสุขที่ฉันคิดว่า ..
Ben Hutchison

"มีผลบังคับใช้" เป็นคำที่ผู้เขียนของโพสต์นั้นเลือกที่จะแปลว่า "มีผลข้างเคียง" เขาพูดอย่างนั้นเอง
Robert Harvey

ฟังก์ชันที่มีประสิทธิภาพของGoogle แสดงให้เห็นหลักฐานมากมายว่าเป็นคำที่ใช้กันอย่างแพร่หลาย โพสต์บล็อกได้รับเป็นหนึ่งในหลาย ๆ ตัวอย่างไม่ใช่เป็นคำจำกัดความ ในวงการการเขียนโปรแกรมเชิงฟังก์ชันที่ฟังก์ชันบริสุทธิ์เป็นค่าเริ่มต้นมีความต้องการคำในเชิงบวกเพื่ออธิบายฟังก์ชั่นผลข้างเคียงโดยเจตนา คือมากกว่าเพียงแค่การขาดของความบริสุทธิ์ มีประสิทธิภาพเป็นคำที่ ตอนนี้พิจารณาตัวเองการศึกษา
Ben Hutchison

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.