การส่งแบบสแตติกประเภทโดยนัย (การบีบบังคับ) ใน Haskell


9

ปัญหา

พิจารณาปัญหาการออกแบบต่อไปนี้ใน Haskell ฉันมีความเรียบง่าย, EDSL สัญลักษณ์ที่ฉันต้องการที่จะแสดงตัวแปรและการแสดงออกทั่วไป (มีหลายชื่อหลายตัวแปร) x^2 * y + 2*z + 1เช่น นอกจากนี้ผมต้องการที่จะแสดงสมสัญลักษณ์บางกว่าการแสดงออกการพูดx^2 + 1 = 1เช่นเดียวกับคำนิยามx := 2*y - 2เช่น

เป้าหมายคือ:

  1. มีประเภทที่แยกต่างหากสำหรับตัวแปรและนิพจน์ทั่วไป - ฟังก์ชันบางอย่างอาจนำไปใช้กับตัวแปรและไม่ใช่นิพจน์ที่ซับซ้อน ตัวอย่างเช่นตัวดำเนินการคำนิยาม:=อาจเป็นประเภท (:=) :: Variable -> Expression -> Definitionและไม่ควรส่งผ่านนิพจน์ที่ซับซ้อนเป็นพารามิเตอร์ด้านซ้ายมือ (แม้ว่ามันจะเป็นไปได้ที่จะส่งตัวแปรเป็นพารามิเตอร์ด้านขวาโดยไม่ต้องมีการแคสต์อย่างชัดเจน ) .
  2. มีตัวอย่างของนิพจน์Numเพื่อให้สามารถส่งเสริมตัวอักษรจำนวนเต็มเป็นนิพจน์และใช้สัญลักษณ์ที่สะดวกสำหรับการดำเนินการเกี่ยวกับพีชคณิตทั่วไปเช่นการบวกหรือการคูณโดยไม่ต้องแนะนำตัวดำเนินการ wrapper เสริม

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

อภิปรายผล

เป็นที่ชัดเจนว่าปัญหาหลักที่นี่คือการNumจำกัด ประเภทของเช่น

(+) :: Num a => a -> a -> a

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

ตัวอย่าง

นึกคิดฉันต้องการบรรลุไวยากรณ์ที่มีน้ำหนักเบาเช่น

computation = do
  x <- variable
  t <- variable

  t |:=| x^2 - 1
  solve (t |==| 0)

โดยเฉพาะฉันต้องการห้ามใช้สัญกรณ์อย่าง t + 1 |:=| x^2 - 1นั้นเนื่องจาก:=ควรให้คำจำกัดความของตัวแปรและไม่ใช่การแสดงออกทางซ้ายมือทั้งหมด


1
บางทีคุณอาจใช้ a class FromVar eพร้อมเมธอดfromVar :: Variable -> eและระบุอินสแตนซ์ให้ExpressionและVariableจากนั้นให้ตัวแปรของคุณมีประเภทโพลีมอร์ฟิคx :: FromVar e => eเป็นต้นฉันไม่ได้ทดสอบว่ามันใช้งานได้ดีแค่ไหนตอนนี้ที่ฉันใช้โทรศัพท์
หมอก.

ฉันไม่แน่ใจว่าตัวFromVarพิมพ์ดีดจะช่วยได้อย่างไร ฉันต้องการที่จะหลีกเลี่ยงการปลดเปลื้องอย่างชัดเจนในขณะที่เก็บตัวอย่างของExpr Numฉันแก้ไขคำถามโดยเพิ่มตัวอย่างของสัญกรณ์ที่ฉันต้องการบรรลุ
Maciej Bendkowski

คำตอบ:


8

เพื่อใช้ประโยชน์จากความหลากหลายมากกว่าการพิมพ์ย่อย (เพราะนั่นคือทั้งหมดที่คุณมีใน Haskell) อย่าคิดว่า "ตัวแปรคือนิพจน์" แต่ "ทั้งตัวแปรและนิพจน์มีการดำเนินการร่วมกัน" การดำเนินการเหล่านั้นสามารถใส่ใน class type:

class HasVar e where fromVar :: Variable -> e

instance HasVar Variable where fromVar = id
instance HasVar Expression where ...

จากนั้นแทนที่จะทำสิ่งต่าง ๆ ทำสิ่งที่หลากหลาย หากคุณมีv :: forall e. HasVar e => eมันสามารถใช้ทั้งการแสดงออกและเป็นตัวแปร

example :: (forall e. HasVar e => e) -> Definition
example v = (v := v)  -- v can be used as both Variable and Expression

 where

  (:=) :: Variable -> Expression -> Definition

โครงกระดูกที่จะทำให้รหัสด้านล่าง typecheck: https://gist.github.com/Lysxia/da30abac357deb7981412f1faf0d2103

computation :: Solver ()
computation = do
  V x <- variable
  V t <- variable
  t |:=| x^2 - 1
  solve (t |==| 0)

น่าสนใจขอบคุณ! ผมถือว่าหลบซ่อนตัวอยู่ทั้งสองตัวแปรและการแสดงออกที่อยู่เบื้องหลังประเภทอัตถิภาวนิยมสำหรับช่วงเวลาสั้น ๆ Vแต่ฉันปฏิเสธความคิดเพราะมันนำมาใช้สัญกรณ์เพิ่มเติมโปรดดูที่ของคุณ เริ่มแรกนั่นไม่ใช่สิ่งที่ฉันต้องการ แต่บางทีฉันก็เร็วเกินไปที่จะยกเลิก ... อาจเป็นไปได้ว่าฉันไม่สามารถกำจัดความทึบแสงVได้ ในบันทึกที่เกี่ยวข้องฉันจะสร้างตัวอย่างได้V (forall e . HasVar e => e)อย่างไร ใน Coq ฉันจะใช้การคำนวณประเภทและการจับคู่รูปแบบกับประเภทอุปนัย แต่ก็ไม่มีความชัดเจนในการบรรลุผลใน Haskell
Maciej Bendkowski

1
คุณสามารถคว้าw :: Variableบางอย่างและนำfromVarไปใช้กับมัน: variable = (\w -> V (fromVar w)) <$> (_TODO_ :: Solver Variable).
หลี่เหยาเซีย

1
และVสามารถหลีกเลี่ยงได้ด้วยประเภทที่มีการเลียนแบบ แต่ก็ยังคงเป็น WIP หรือเราสามารถให้variableใช้ความต่อเนื่องที่มีการโต้แย้ง polymorphic (>>=)อย่างชัดเจนแทนทางอ้อมผ่านทาง
หลี่เหยาเซีย
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.