简体   繁体   中英

Syntax for partial function composition

module Luhn (isValid) where

import qualified Data.Char as C

isAsciiAlpha :: Char -> Bool
isAsciiAlpha = C.isAsciiLower || C.isAsciiUpper

isValid :: String -> Bool
isValid n
  | any ((isAsciiAlpha || C.isSpace) . not) n = False
  | otherwise = ys > 1 && sum xxs `mod` 10 == 0
  where
    xs = reverse [c | c <- n, isAsciiAlpha c]
    ys = length xs
    zs = zip xs (cycle [1, 2])
    xxs = [convert x y | (x, y) <- zs]

convert :: Char -> Int -> Int
convert c mul =
  do
    let n = C.digitToInt c
    case () of
      _
        | mul == 2 && (n > 4) -> n * mul - 9
        | otherwise -> n * mul

I'm struggling with this line: any ((isAsciiAlpha || C.isSpace) . not) n = False . What I want is pretty obvious; find if any of the characters is something other than an ASCII alphabet or a space.

In spite of trying various syntaxes, I keep getting compilation error on this line, something like

• Couldn't match expected type ‘Bool’
                  with actual type ‘Char -> Bool’

You can not use (||) :: Bool -> Bool -> Bool on two functions: the parameters should be both Bool s. What you can do is construct a function that maps a character c on isAsciiAlpha c || C.isSpace c isAsciiAlpha c || C.isSpace c , so \c -> isAsciiAlpha c || C.isSpace c \c -> isAsciiAlpha c || C.isSpace c , or you can use liftA2 :: Applicative f => (a -> b -> c) -> fa -> fb -> fc with liftA2 (||) isAsciiAlpha C.isSpace . The not :: Bool -> Bool should also be applied on the result of the function, so:

import Control.Applicative(liftA2)

isAsciiAlpha :: Char -> Bool
isAsciiAlpha = liftA2 (||) C.isAsciiLower C.isAsciiUpper

isValid :: String -> Bool
isValid n
  | any (not . liftA2 (||) isAsciiAlpha C.isSpace) n = False
  | otherwise = ys > 1 && sum xxs `mod` 10 == 0
  where -- …

You can also make use of (<||>) :: Applicative a => a Bool -> a Bool -> a Bool or its shortcircuitng version (||^) :: Monad m => m Bool -> m Bool -> m Bool of the protolude package .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM