Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Haskell point-free

Name: Anonymous 2009-12-25 17:12

I have this:


ops :: [[Char] -> [Char]]
...
fun :: [Char] -> [[Char]]
fun str = zipWith ($) ops $ words str


How do I write fun in a point-free style? Dropping the argument gives me type errors.

Name: Anonymous 2010-01-09 15:26

>>47
tl;dr: use liftM2

liftM :: Monad m => (a -> b) -> (m a -> m b)
elem :: (a -> ([a] -> Bool))
liftM elem :: Monad m => m a -> m ([a] -> Bool)
liftM elem (Just 'd') :: Monad m => Maybe ([a] -> Bool)


Can you see why that doesn't work? You can't apply that to Just "dongz", because it's not a function: it is a nomad with the function in his pocket. What you really want is liftM2:

liftM2 :: Monad m => (a -> b -> c) -> (m a -> m b -> m c)
liftM2 elem :: Monad m => m a -> m [a] -> m Bool
liftM2 elem (Just 'd') (Just "dongz") :: Maybe Bool


But I won't stop here, because there's another interesting way, namely the Applicative type class. I recommend the the Typeclassopedia¹ for understanding this and its relationship to the others, but here's an introduction.

class Functor f => Applicative f where
    pure :: a -> f a -- For a monad, pure = return

    -- This is why it is called an applicative functor.
    --
    -- For any monad, you can define <*> as such:
    --   f <*> x = liftM2 ($) f x
    --
    -- There are applicatives which are not monads, such as the ZipList
    -- applicative (as far as I know).
    --
    -- E.g. in the Maybe monad this is
    --   Maybe (a -> b) -> (Maybe a -> Maybe b)
    (<*>) :: f (a -> b) -> (f a -> f b)

-- This is already defined in Control.Applicative.
instance Applicative Maybe where
    pure = Just
    Just f <*> Just x = Just (f x)
    _ <*> _ = Nothing

-- Just succ <*> Just 3 = Just 4
-- [succ, (*2)] <*> [7,8] = [8,9,14,16]
-- (zip <*> tail) [1..10] = [(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10)]

liftM elem :: Monad m => m a -> m ([a] -> Bool)
liftM elem (Just 'd') :: Maybe ([a] -> Bool)
(<*>) liftM elem (Just 'd') :: Maybe [a] -> Maybe Bool
liftM elem (Just 'd') <*> Just "dongz" :: Maybe Bool


Now, if you define <$> = liftM², you get a nice result:

elem <$> (Just 'd') <*> Just "dongz" :: Maybe Bool

Alternative, but equivalent answers:

pure elem <*> (Just 'd') <*> Just "dongz" :: Maybe Bool
elem `liftM` (Just 'd') `ap` Just "dongz" :: Maybe Bool


¹ http://haskell.org/sitewiki/images/8/85/TMR-Issue13.pdf
² Or <$> = fmap, it's the same since liftM = fmap.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List