`A =› List[B]` สามารถแปลงเป็น `List[A =› B]` ได้หรือไม่

ฉันกำลังพยายามค้นหาการใช้งานสำหรับลายเซ็นฟังก์ชัน Scala นี้:

def explode[A, B](f: A => List[B]): List[A => B]

ทิศทางตรงกันข้ามเป็นไปได้:

def nest[A, B](fs: List[A => B]): A => List[B] = (a: A) => fs.map(_(a))

ถึงตอนนี้ฉันมีแนวโน้มที่จะเชื่อว่าอันแรก (explode) นั้นใช้งานไม่ได้ แต่ฉันดีใจที่ได้รับการพิสูจน์แล้วว่าผิด หากไม่สามารถนำไปปฏิบัติได้จริง มีเหตุผลเชิงลึกเบื้องหลังหรือไม่?

ในมุมมองของฉัน ฉันขอให้คอมไพเลอร์ทำซ้ำอินพุตนั้น A บาง n ครั้ง (ขนาด Lists) และแก้ไขเป็นอินพุต


person Eliav Lavi    schedule 26.12.2020    source แหล่งที่มา
comment
@LuisMiguelMejíaSuárez ดูที่นี่ . (นอกจากนี้ ฟังก์ชันเหล่านี้ก็ไม่ได้เหมือนกันทั้งหมด แต่ละฟังก์ชันให้ผล B ที่แตกต่างกัน)   -  person Eliav Lavi    schedule 27.12.2020
comment
ใช่ขอโทษ. ฉันยังคิดว่ามันคุ้มค่าที่จะอธิบายสิ่งที่คุณต้องการทำ   -  person Luis Miguel Mejía Suárez    schedule 27.12.2020
comment
ทำไมคุณไม่ทำงานกับรายการสิ่งอันดับ? หรือแผนที่? อะไรประมาณนั้น: def explode[A, B](f: A => List[B])(a: A): List[(A, B)] = { f(a).map(b => a -> b) } ?   -  person Tomer Shetah    schedule 27.12.2020


คำตอบ (2)


ในมุมมองของฉัน ฉันขอให้คอมไพเลอร์ทำซ้ำอินพุตนั้น A บาง n ครั้ง (ขนาด Lists) และแก้ไขเป็นอินพุต

ปัญหาคือคุณไม่รู้ว่า n คืออะไร ลองพิจารณาตัวอย่างฟังก์ชันที่คืนค่ารายการตัวหารเฉพาะของตัวเลข:

def divisors(n: Int): List[Int] = ???

คุณคาดหวังว่า explode(divisors) จะเป็นอย่างไร? divisors สามารถส่งคืน List ขนาดใดก็ได้ ขึ้นอยู่กับอาร์กิวเมนต์ เมื่อใดก็ตามที่มีการเรียกใช้ในอนาคต แต่เมื่อคุณโทร explode มันจะต้องส่งคืน List ของขนาดคงที่ทันที

ด้วยประเภทคงที่ A ลายเซ็นในโค้ดของคุณสามารถเขียนได้ดังนี้:

type F[T] = List[T]
type G[T] = A => T

def nest[B]: F[G[B]] => G[F[B]]
def explode[B]: G[F[B]] => F[G[B]]

nest และ explode ชวนให้นึกถึงการดำเนินการ sequence มันใช้ได้กับ nest เพราะเป็นไปได้ที่จะเขียนอินสแตนซ์ Traverse สำหรับ List แต่ ไม่สามารถเขียนอินสแตนซ์ Traverse สำหรับฟังก์ชัน A => T ได้ นี่คือคำถามที่เทียบเท่าสำหรับ Haskell ที่ให้ข้อมูลเชิงลึกมากขึ้น

person Kolmar    schedule 26.12.2020
comment
ขอบคุณสำหรับการตอบกลับข้อมูลของคุณ! คุณเขียนว่า ...แต่เมื่อคุณโทร nest มันจะต้องส่งคืน List ที่มีขนาดคงที่ทันที (ฉันเชื่อว่าคุณหมายถึง explode) และนั่นก็เป็นความจริง ฉันกำลังพยายามคิดว่าคำตอบอาจแตกต่างออกไปหากฉันยอมสละส่วนที่รายการส่งคืนด้วยขนาดคงที่ทันที - จะเป็นอย่างไรหากฉันต้องทำงานกับ Stream / LazyList ฯลฯ - person Eliav Lavi; 26.12.2020
comment
ฉันคิดว่า Stream ยังไม่ดีอยู่ เพราะสามารถหมดได้ทันที เช่น explode(divisors).toList. และ List อาจต้องเว้นว่างไว้สำหรับบาง n มันเป็นคำถามเชิงทฤษฎีหรือคุณมีปัญหาที่ต้องการแก้ไขหรือไม่? - person Kolmar; 26.12.2020
comment
ฉันเห็นสิ่งที่คุณหมายถึง ฉันคิดว่าที่ว่างเปล่า List สามารถทำงานได้ดี แต่สาระสำคัญยังคงอยู่ที่ชั้นเชิง นี่เป็นทฤษฎีเป็นส่วนใหญ่ แต่เกิดจากโปรเจ็กต์ข้างเคียงที่ฉันกำลังทดลอง ฉันเกรงว่าการให้บริบทที่มีรายละเอียดมากขึ้นจะซับซ้อนเกินไปและจะไม่ช่วยอะไร โดยพื้นฐานแล้วนี่หมายความว่าฉันควรมองหาทิศทางอื่นในการสร้างแบบจำลองปัญหาของฉัน - person Eliav Lavi; 27.12.2020

หากคุณต้องการใช้งานบางอย่างที่ตรงตามลายเซ็น คุณสามารถดำเนินการดังนี้:

def explode[A, B](f: A => List[B]): List[A => B] = {
  Nil
}

def explode[A, B](f: A => List[B]): List[A => B] = {
  List(f.andThen(_.head))
}

แต่ฉันเดาว่าคุณต้องการบางสิ่งที่แตกต่างความหมาย:

ทำซ้ำอินพุต A n ครั้ง (ขนาดรายการ) และแก้ไขเป็นอินพุต

ในกรณีนั้นมีปัญหา. ผลลัพธ์ของ f ในกรณีทั่วไป ขึ้นอยู่กับอินพุต A อาจเป็น Nil รายการที่มีขนาดจำกัด หรือรายการที่ไม่มีที่สิ้นสุด

สิ่งที่คุณสามารถทำได้มีเพียงบางอย่างเช่น:

def explode[A, B](f: A => List[B]): A => List[A => B] = {
  f.andThen(_.map(b => (_: A) => b)
}
person Artem Sokolov    schedule 26.12.2020