import Data.Char (isLower, isAscii)
import Test.QuickCheck
-- 1ª solución
alfabetoDesde1 :: Char -> String
alfabetoDesde1 c =
dropWhile (<c) ['a'..'z'] ++ takeWhile (<c) ['a'..'z']
-- 2ª solución
alfabetoDesde2 :: Char -> String
alfabetoDesde2 c = ys ++ xs
where (xs,ys) = span (<c) ['a'..'z']
-- 3ª solución
alfabetoDesde3 :: Char -> String
alfabetoDesde3 c = ys ++ xs
where (xs,ys) = break (==c) ['a'..'z']
-- 4ª solución
alfabetoDesde4 :: Char -> String
alfabetoDesde4 c
| 'a' <= c && c <= 'z' = [c..'z'] ++ ['a'..pred c]
| otherwise = ['a'..'z']
-- 5ª solución
alfabetoDesde5 :: Char -> String
alfabetoDesde5 c
| isLower c = [c..'z'] ++ ['a'..pred c]
| otherwise = ['a'..'z']
-- Comprobación de equivalencia
-- ============================
-- La propiedad es
prop_alfabetoDesde :: Property
prop_alfabetoDesde =
forAll (arbitrary `suchThat` isAscii) $ \c ->
all (== alfabetoDesde1 c)
[f c | f <- [alfabetoDesde2,
alfabetoDesde3,
alfabetoDesde4,
alfabetoDesde5]]
-- La comprobación es
-- λ> quickCheck prop_alfabetoDesde
-- +++ OK, passed 100 tests.