使用(ceiling . sqrt)在Haskell范围表达式中触发错误求助
Hey there! As someone who’s stumbled through early Haskell pitfalls too, let’s break down what’s probably tripping you up with your prime checker, and share some solid resources to help you level up.
The Core Issue: ceiling . sqrt & Range Logic
First, let’s unpack two key points that might be causing unexpected behavior:
1. Type Mismatch Gotchas
sqrt operates on Floating types (like Double), but your prime-checking input is almost certainly an Integral type (like Int or Integer). When chaining ceiling . sqrt, you need to explicitly convert your Integral value to a Floating one with fromIntegral—otherwise GHC will throw a type error. Even if you handled that, there’s a logical quirk here:
2. Logical Error with ceiling vs floor
Prime checking only needs to test divisors up to the integer square root of your number. If a number n has a factor larger than sqrt(n), its corresponding pair factor will be smaller than sqrt(n)—so we don’t need to check beyond that.
- Using
ceiling (sqrt (fromIntegral n))can lead to false negatives for small primes. For example:sqrt 2 ≈ 1.414,ceilinggives 2. Your range would be[2..2], and2mod2 == 0would incorrectly mark 2 as non-prime.
- Switching to
floor (sqrt (fromIntegral n))fixes this: forn=2,floor 1.414 = 1, so the range[2..1]is empty, andallreturns True (correctly marking 2 as prime).
Fixed Prime Checker Example
Here’s a revised version that addresses these issues:
isPrime :: Integral a => a -> Bool isPrime n | n <= 1 = False -- Numbers ≤1 aren't primes | n == 2 = True -- 2 is the only even prime | even n = False -- Even numbers >2 can't be primes | otherwise = all (\x -> n `mod` x /= 0) [3,5..floor (sqrt (fromIntegral n))]
- We skip even numbers after checking 2 to make the function faster.
- The range
[3,5..]steps by 2 to only test odd divisors.
Recommended Haskell Tutorial Content
To deepen your understanding of these concepts, focus on these sections in popular free resources:
- Learn You a Haskell for Great Good!:
- Starting Out: Master range expressions and basic list operations.
- Types and Typeclasses: Understand how Integral, Floating, and type conversions (like
fromIntegral) work. - Higher Order Functions: Get comfortable with function composition (using
.) andall/anyfor list checks.
- Haskell Programming from First Principles:
- The Typeclasses chapter dives deep into the relationships between numeric types, which will clarify why
sqrtandceilingplay nice only with certain types.
- The Typeclasses chapter dives deep into the relationships between numeric types, which will clarify why
- Real World Haskell:
- The Basic Haskell section covers practical list processing and function composition, which are foundational for writing utilities like prime checkers.
Pro tip: Use GHCi’s :t command to inspect the type of any expression (e.g., :t ceiling . sqrt or :t fromIntegral). This is a lifesaver for debugging type-related errors early on!
内容的提问来源于stack exchange,提问作者clocker

