วิธีประกาศฟังก์ชั่น (พิมพ์ผิดอาจจะ)

ฉันต้องการฟังก์ชั่นที่ทำงานเช่น:

some :: (Int, Maybe Int) -> Int
some a b
     | b == Nothing = 0
     | otherwise = a + b

กรณีการใช้งาน:

some (2,Just 1)
some (3,Nothing)
map some [(2, Just 1), (3,Nothing)]

แต่รหัสของฉันทำให้เกิดข้อผิดพลาด:

The equation(s) for `some' have two arguments,
but its type `(Int, Maybe Int) -> Int' has only one

ฉันไม่เข้าใจมัน

ขอบคุณล่วงหน้า.


person demas    schedule 06.12.2010    source แหล่งที่มา
comment
คุณอาจสนใจคำถามทั่วไปเกี่ยวกับวิธีการทำงานกับประเภท Maybe a ตอบแล้วที่นี่   -  person Thomas M. DuBuisson    schedule 07.12.2010


คำตอบ (2)


เมื่อคุณเขียน

foo x y = ...

นั่นคือสัญลักษณ์สำหรับฟังก์ชัน curried ซึ่งมีรูปแบบดังนี้:

foo :: a -> b -> c

คุณได้ประกาศฟังก์ชันของคุณให้คาดหวังสิ่งอันดับ ดังนั้นคุณต้องเขียนมัน:

some :: (Int, Maybe Int) -> Int
some (x, y) = ...

แต่แบบแผนของ Haskell มักจะใช้การโต้แย้งในรูปแบบเดิม การเห็น funcitons รับสิ่งอันดับเนื่องจากการโต้แย้งนั้นหายากมาก

สำหรับอีกส่วนหนึ่งของคำถาม คุณอาจต้องการแสดงด้วยการจับคู่รูปแบบ คุณสามารถพูดได้ว่า:

foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just x) = x + 1

สรุปว่าสำหรับคำถามของ OP นั้นถือเป็นแบบฝึกหัดสำหรับผู้อ่าน

person luqui    schedule 06.12.2010
comment
ขอบคุณ. การจับคู่รูปแบบเป็นสิ่งที่ฉันต้องการ - person demas; 06.12.2010
comment
แทนที่จะจับคู่รูปแบบ ฉันอาจจะเขียนมัน some a b = fromMaybe 0 (fmap (+ a) b) และไม่ชี้ไปที่ some a = fromMaybe 0 . fmap (+ a) - person John L; 06.12.2010
comment
@ จอห์น คุณคิดว่ามันมีประโยชน์ไหมที่จะแนะนำให้ใช้ Functors และสไตล์ไร้จุดให้กับคนที่ยังไม่เข้าใจการแกงและการจับคู่รูปแบบ? - person adamse; 08.12.2010

ข้อผิดพลาดของคุณไม่ได้มาจากความเข้าใจผิดเกี่ยวกับ Maybe: ประเภทของลายเซ็นของ some ระบุว่าต้องใช้คู่ (Int, Maybe Int) ในขณะที่คำจำกัดความของคุณ คุณระบุอาร์กิวเมนต์ไว้สองข้อ คำจำกัดความควรเริ่มต้นด้วย some (a,b) เพื่อให้ตรงกับลายเซ็นประเภท

วิธีหนึ่งในการแก้ไขปัญหา (ซึ่งเป็นสำนวนมากกว่าเล็กน้อยและใช้การจับคู่รูปแบบ) คือ:

some :: (Int, Maybe Int) -> Int
some (a, Nothing) = a
some (a, Just b) = a + b

นอกจากนี้ยังเป็นที่น่าสังเกตว่าหากคุณไม่มีเหตุผลที่ดีจริงๆ ในการใช้ทูเพิลเป็นอินพุต คุณก็ไม่ควรทำเช่นนั้น หากลายเซ็นของคุณเป็น some :: Int -> Maybe Int -> Int แทน คุณจะมีฟังก์ชันสองอาร์กิวเมนต์ ซึ่งสามารถ curried ได้ . แล้วคุณจะเขียนบางอย่างเช่น

some :: Int -> Maybe Int -> Int
some a Nothing = a
some a (Just b) = a + b

นอกจากนี้ คุณอาจต้องการเพิ่มลักษณะทั่วไปต่อไปนี้: Num ประเภททั้งหมดเป็นการบวก ดังนั้นคุณก็อาจทำได้เช่นกัน

some :: (Num n) => n -> Maybe n -> n
some a Nothing = a
some a (Just b) = a + b

(ฉันได้ละเมิดหลักปฏิบัติทั่วไปในการใช้ a, b, c... สำหรับตัวแปรประเภทเพื่อไม่ให้ OP สับสนเนื่องจากเขาผูก a และ b กับอาร์กิวเมนต์ของ some)

person gspr    schedule 06.12.2010