“ การเป็นตัวแทนที่ยกขึ้น” คืออะไร?


12

เพิ่งวิ่งข้ามคำนี้ที่นี่:

http://www.codemesh.io/codemesh2014/viktor-klang

"เราจะแสดงให้เห็นถึง Flow API - การนำเสนอแบบยก - เช่นเดียวกับวิธีที่เปลี่ยนแปลงได้ในการเปลี่ยนการนำเสนอแบบยกเป็นการดำเนินการแทน - Flow Materialization"

Googling ไม่ได้ช่วยอะไรมาก


การอ่านที่แนะนำ: อภิปราย $ {บล็อก} นี้
gnat

11
@ ดูเหมือนว่าเขาไม่ได้ประดิษฐ์คำนั้นมันไม่เหมือนความเห็นมันไม่น่าจะทำให้เกิดการอภิปรายและความรู้สึกของฉันคือว่ามันจะไม่กว้างเกินไป (แม้ว่าจะรู้สึกเหมือนคณิตศาสตร์)
Den

2
ฉันพูดถึงความหมายของ "ยก" ในบริบทของ C # ที่นี่: blogs.msdn.com/b/ericlippert/archive/2007/06/27/ … - ผู้พัฒนา Scala กำลังใช้คำนี้ในแบบอะนาล็อกแต่มีมากกว่า แฟชั่นทั่วไป
Eric Lippert

คำตอบ:


22

ฉันไม่คุ้นเคยกับ Flow API

คำว่า "การยก" มาจากทฤษฎีหมวดหมู่ ในการเขียนโปรแกรมภาษาเช่น Haskell หรือสกาล่าซึ่งเป็นliftฟังก์ชั่นใช้เวลาฟังก์ชั่นA => Bและอย่างใดดำเนินมายากลเพื่อให้ฟังก์ชั่นยกF[A] => F[B]สามารถนำไปใช้กับ functor หรือ F[A]monad

ตัวอย่างที่เป็นรูปธรรมโดยใช้ Scala ของSeqภาชนะ: สมมติเรามีฟังก์ชั่นและลำดับที่def double(x: Int): Int = 2 * x val xs = Seq(1, 2, 3)เราไม่สามารถdouble(xs)เนื่องจากประเภทที่เข้ากันไม่ได้ แต่ถ้าเราได้รับval doubleSeq = liftToSeq(double)ที่เราสามารถทำได้ซึ่งประเมินdoubleSeq(xs) Seq(2, 4, 6)ที่นี่liftToSeqสามารถนำไปใช้เป็น

def liftToSeq[A, B](f: A => B): (Seq[A] => Seq[B]) =
  (seq: Seq[A]) => seq.map(f)

คอนSeq(…)สตรัคเตอร์ยังสามารถมองเห็นได้ว่าเป็นการดำเนินการยกซึ่งยกค่า1, 2, 3ลงในSeqตัวอย่างจึงช่วยให้เราสามารถใช้รายการนามธรรมสำหรับค่าเหล่านี้

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


4
นั่นเป็นคำอธิบายที่ดีเกี่ยวกับคณิตศาสตร์ "การยก" นอกจากนี้เรายังควรจะมีการอ้างอิงถึงคำอธิบายอย่างเป็นทางการของการยกจากวิกิพีเดีย
Scott Whitlock

3
ตัวอย่างที่ชัดเจนกว่าของ "การยก" คือการยกให้เป็นประเภท nullable (หรือ "ไม่จำเป็น" หรือ "อาจจะ") ตัวอย่างเช่นสมมติว่าคุณมีผู้ประกอบการที่กำหนดไว้ดังกล่าวว่า+ int + int --> intยกไป nullable ผู้ประกอบการint? + int? --> int?มีความหมายของ "ถ้าทั้งตัวถูกดำเนินการเป็นโมฆะแล้วคำตอบเป็นโมฆะมิฉะนั้นใช้ประกอบการที่ไม่ได้ปลดค่า"
Eric Lippert

@ScottWhitlock คุณยังยกได้หรือไม่
helrich

1
@ Frank ฉันอ่านบทความ Wikipedia ก่อนที่จะเขียนคำตอบและก็ไม่เข้าใจเหมือนกัน แต่ผมพบว่าHaskell วิกิพีเดียในยกที่จะเข้าถึงได้มากขึ้น โปรดทราบว่าเราไม่มีสี่ประเภทจริง ๆ เรามีคอนกรีตสี่ประเภท แต่มีเพียงสามประเภทตัวแปร: สองประเภทและและ functor ซึ่งเป็นตัวสร้างประเภท ABF
amon

1
ฉันไม่ได้ลึกเข้าไปในทั้งหมดนี้ แต่ถ้าFเป็นตัวสร้างประเภทแล้วก็F[A]เป็นหนึ่งในประเภทที่สร้างขึ้น เหตุใดจึงผิดที่จะพูดถึงสี่ประเภทนี้ (สองประเภทและคอนสตรัคเตอร์ประเภทเดียวคงไม่ต่างกันเท่าไร)
Frank

6

แน่นอนว่าคำว่ายกจะมีความหมายแตกต่างกันไปตามบริบท

ในการเขียนโปรแกรมทั่วไปจะอธิบายกระบวนการของการสรุปเป็นระดับที่สูงขึ้นต่อไป ตัวอย่างเช่นคุณอาจมีสองชิ้นของรหัสชนิดหนึ่งที่มีintและอื่น ๆ floatที่มี ยกรหัสนี้จะหมายถึงสิ่งที่ต้องการ templating วิธีการที่มีประเภททั่วไปTที่เหมาะกับทั้งสองและintfloat

ฉันพบว่าการใช้คำนี้เป็นแนวทางที่ใช้งานง่ายสำหรับการยกความหมาย ความแตกต่างเพียงอย่างเดียวที่ดูเหมือนจะมีอยู่ระหว่างบริบทที่แตกต่างคือสิ่งที่เป็นนามธรรมที่สูงกว่านี้จริงๆ

โดยเฉพาะอย่างยิ่ง Viktor เป็นที่รู้จักในบริบทของการเขียนโปรแกรมการทำงานและในบริบทนี้คุณสามารถค้นหาการตีความที่แตกต่างกันอย่างเห็นได้ชัดของการยกที่นั่น ตัวอย่างหนึ่งคือการยกค่าให้เป็น functor หรือเพื่อยกฟังก์ชั่นการทำงานกับค่า monadic (เช่น Haskell's liftM2)

ตัวอย่างที่เป็นรูปธรรมของ "ตัวแทนที่ยกขึ้น" นั้นสามารถ f.ex จะเป็นหรือList(1)Some(1)


4

แนวความคิดประเภทนี้มักจะเข้าใจง่ายที่สุดด้วยตัวอย่างที่เป็นรูปธรรม พิจารณาข้อความที่ตัดตอนมาจากตัวอย่าง Flow APIนี้:

Flow(text.split("\\s").toVector).
      // transform
      map(line => line.toUpperCase).
      // print to console (can also use ``foreach(println)``)
      foreach(transformedLine => println(transformedLine)).
      onComplete(FlowMaterializer(MaterializerSettings())) {
        case Success(_) => system.shutdown()
        case Failure(e) =>
          println("Failure: " + e.getMessage)
          system.shutdown()
      }

ใช้รหัสต่อไปนี้:

text.split("\\s").toVector.
      map(line => line.toUpperCase).
      foreach(println)

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

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

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