การใช้คำนี้ฟังก์ชั่นเป็นไปได้โดยไม่ต้องขั้นตอน postprocessing หลังจากพับหรือไม่?


14

Real World Haskell, ตอนที่ 4, หน้า 98 ของการพิมพ์ถามว่าwordsสามารถนำไปใช้โดยใช้ folds หรือไม่และนี่คือคำถามของฉันเช่นกัน:

เป็นไปได้ไหม? ถ้าไม่ทำไม ถ้ามันเป็นอย่างไร

ฉันคิดว่าสิ่งต่อไปนี้จะขึ้นอยู่กับความคิดที่ว่าแต่ละช่องว่างควรจะเติมคำสุดท้ายในรายการเอาท์พุท (นี้เกิดขึ้นในotherwiseยาม) และช่องว่างที่ควรจะเพิ่มคำ emtpy รายการเอาท์พุทหากยังไม่ได้มีอยู่ (มีการจัดการในif- then- else)

myWords :: String -> [String]
myWords = foldr step [[]]
  where
    step x yss@(y:ys)
      | x == ' ' = if y == "" then yss else "":yss
      | otherwise = (x:y):ys

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

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

วิธีการอื่น ๆ ใช้ tuples (อันที่จริงแค่จับคู่) ดังนั้นการพับที่เกี่ยวข้องกับคู่และสามารถจัดการช่องว่างนำหน้า / ท้าย

ในวิธีการเหล่านี้ทั้งหมดfoldr(หรืออีกโฟลด์, fwiw) ไม่ได้เป็นฟังก์ชั่นที่ให้ผลลัพธ์สุดท้ายออกจากกล่อง; มีอย่างอื่นที่มีการปรับเอาท์พุทอย่างใด

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

myWords :: String -> [String]
myWords input = foldr step seed input

คำตอบ:


13

หากฉันเข้าใจถูกต้องความต้องการของคุณจะรวมอยู่ด้วย

(1) words "a b c" == words " a b c" == ["a", "b", "c"]
(2) words "xa b c" == ["xa", "b", "c"] /= ["x", "a", "b", "c"] == words "x a b c"

นี่ก็หมายความว่าเราไม่สามารถมีได้

words = foldr step base

สำหรับการใด ๆและstepbase

แน่นอนถ้าเรามีสิ่งนั้น

words "xa b c"
= def words and foldr
step 'x' (words "a b c")
= (1)
step 'x' (words " a b c")
= def words and foldr
words "x a b c"

และสิ่งนี้ขัดแย้ง (2)

foldrแน่นอนคุณต้องมีการโพสต์หลังจากที่


1
ฉันรักภาษานี้มากขึ้น ...
Enrico Maria De Angelis

หรือแม้กระทั่ง["xa"] == words "xa" == step 'x' (words "a") == step 'x' (words " a") == words "x a" == ["x", "a"]ซึ่งมีประโยชน์ในการเป็นอาร์กิวเมนต์ที่ถูกต้องสำหรับทิศทางของการพับ
Cireo

5

@chi มีข้อโต้แย้งที่ยอดเยี่ยมที่คุณจะไม่สามารถดำเนินการwordsได้โดยใช้ "เป็น" พับ แต่ไม่บอกว่าใช้เท่า s

words = filterNull . words1
    where
    filterNull = foldr (\xs -> if null xs then id else (xs:)) []
    words1 = foldr (\c -> if c == ' ' then ([]:) else consHead c) []
    consHead c []       = [[c]]
    consHead c (xs:xss) = (c:xs):xss

ทั้งฟังก์ชั่นนอกสุดและสุดคือพับ ;-)


ฉันคิดว่าคุณรู้ว่าฉันหมายถึงอะไร แต่ +1 สำหรับการจู้จี้จุกจิก: P
Enrico Maria De Angelis

1

ใช่. แม้จะเป็นเรื่องยากเล็กน้อยที่คุณอาจยังคงทำงานนี้ได้อย่างถูกต้องโดยใช้ซิงเกิ้ลfoldrและไม่มีอะไรอื่นถ้าคุณอาศัยอยู่ใน CPS ( สไตล์การส่งต่ออย่างต่อเนื่อง ) chunksOfก่อนหน้านี้ฉันได้แสดงฟังก์ชั่นพิเศษชนิดหนึ่ง

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

ws :: String -> [String]
ws str = foldr go sf str $ ""
         where
         sf :: String -> [String]
         sf s = if s == " " then [""] else [s]
         go :: Char -> (String -> [String]) -> (String -> [String])
         go c f = \pc -> let (s:ss) = f [c]
                         in case pc of
                            ""        -> dropWhile (== "") (s:ss)
                            otherwise -> case (pc == " ", s == "") of
                                         (True, False)  -> "":s:ss
                                         (True, True)   -> s:ss
                                         otherwise      -> (pc++s):ss

λ> ws "   a  b    c   "
["a","b","c"]

sf : ค่าฟังก์ชั่นเริ่มต้นที่จะเริ่มต้นด้วย

go : ฟังก์ชั่นตัววนซ้ำ

ที่จริงแล้วเราไม่ได้ใช้ประโยชน์จากพลังของ CPS อย่างเต็มที่เนื่องจากเรามีทั้งตัวละครก่อนหน้าpcและตัวละครที่โค้งcในทุก ๆ เทิร์น มันมีประโยชน์มากในchunksOfฟังก์ชั่นที่กล่าวถึงข้างต้นในขณะที่การสอด[Int]เข้าไปใน[[Int]]ทุกครั้งที่ลำดับขององค์ประกอบที่แตกหัก

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