[Haskell-beginners] Extracting arguments point-free

Peter Hall peter.hall at memorphic.com
Sun Mar 25 01:45:38 CET 2012


Ok, I got it. I was confusing myself with <$> and some of those are
clearer with map. I ended up with this, which I'm happy with:

run :: IO Int
run = return $ calc [1..999]

calc :: [Int] -> Int
calc = sum . filter isBinaryPalindrome . decimalPalindromes

isBinaryPalindrome :: Int -> Bool
isBinaryPalindrome = (==) <$> (fromDigitsB . reverse . digitsB) <*> id

decimalPalindromes :: [Int] -> [Int]
decimalPalindromes = map fromDigitsD . oddsAndEvens . map digitsD
        where oddsAndEvens  = (++) <$> (map oddDigits) <*> (map evenDigits)
              evenDigits    = (++) <$> id              <*> reverse
              oddDigits     = (++) <$> reverse . tail  <*> id




Peter

On 24 March 2012 21:18, Peter Hall <peter.hall at memorphic.com> wrote:
> As an exercise I'm trying to rewrite a Project Euler solution below to
> be as point-free as possible.  I'm stuck trying to extract the
> [1..999] range so it can be passed as an argument to calc. Can someone
> help me figure it out?
>
> Thanks,
> Peter
>
>
> module Problem0036 (
>    run
> ) where
>
> import Num.Digits
> import Control.Applicative
>
> run :: IO Int
> run = return $ calc
>
> calc :: Int
> calc = sum $ filter isBinaryPalindrome decimalPalindromes
>
> isBinaryPalindrome :: Int -> Bool
> isBinaryPalindrome = (==) <$> (fromDigitsB . reverse . digitsB) <*> id
>
> decimalPalindromes :: [Int]
> decimalPalindromes = fromDigitsD <$> oddsAndEvens (digitsD <$> [1..999])
>        where oddsAndEvens  = (++) <$> (oddDigits <$>) <*> (evenDigits <$>)
>              evenDigits    = (++) <$> id              <*> reverse
>              oddDigits     = (++) <$> reverse . tail  <*> id
>
>
>
>
> -- The other imported module:
>
> module Num.Digits (
>     digits
>    ,digitsD
>    ,digitsB
>    ,fromDigits
>    ,fromDigitsB
>    ,fromDigitsD
> ) where
>
> import Data.Char (digitToInt)
> import Data.List (insert, foldl1')
>
> {-# INLINABLE digitsD #-}
> digitsD :: Integral a => a -> [a]
> digitsD = digits 10
>
> {-# INLINABLE fromDigitsD #-}
> fromDigitsD :: Integral a => [a] -> a
> fromDigitsD = fromDigits 10
>
> {-# INLINABLE digitsB #-}
> digitsB :: Integral a => a -> [a]
> digitsB = digits 2
>
> {-# INLINABLE fromDigitsB #-}
> fromDigitsB :: Integral a => [a] -> a
> fromDigitsB = fromDigits 2
>
> {-# INLINABLE digits #-}
> digits :: Integral a => a -> a -> [a]
> digits b 0 = [0]
> digits b n = reverse $ digits' n
>    where digits' 0 = []
>          digits' n = r : digits' q
>            where (q,r) = quotRem n b
>
> {-# INLINABLE fromDigits #-}
> fromDigits :: Integral a => a -> [a] -> a
> fromDigits b = foldl1' (\i j -> b * i + j)



More information about the Beginners mailing list