[Haskell-beginners] (.) vs ($)

Vale Cofer-Shabica vale.cofershabica at gmail.com
Sat Apr 4 19:31:52 UTC 2015


Thank you for all the responses! Sumit's point about function
application binding most strongly was the point I was missing. I was
lured by the possibility of writing my function in point-free style as
Mike indicated: readFirst = readFile.head, but ghc complained about
differing numbers of arguments when I included the different case for
the empty list.

Thanks again,
vale



On Sat, Apr 4, 2015 at 1:46 AM, Sumit Sahrawat, Maths & Computing, IIT
(BHU) <sumit.sahrawat.apm13 at iitbhu.ac.in> wrote:
> To reiterate what others have said,
>
>    readFile . head xs
> == readFile . (head xs)     { function application binds strongest }
> == (.) readFile (head xs)   { operators are also functions }
>
> The types,
>
>    (.)      :: (b -> c) -> (a -> b) -> (a -> c)
>    readFile :: FilePath -> IO String
>    head xs  :: FilePath
>
> This cannot work as the types don't match. On the other hand, using ($)
> instead of (.) will work.
> Try writing that out and reasoning with the types on pen and paper, as an
> exercise.
>
> If you're interested, there is an excellent post about equational reasoning
> here: http://www.haskellforall.com/2013/12/equational-reasoning.html
>
> Enjoy :)
>
> On 4 April 2015 at 08:10, Mike Meyer <mwm at mired.org> wrote:
>>
>> As is often the case with Haskell, your answer is in the types:
>>
>> Prelude> :t ($)
>> ($) :: (a -> b) -> a -> b
>> Prelude> :t (.)
>> (.) :: (b -> c) -> (a -> b) -> a -> c
>>
>> So $ takes a function and applies it to a value. . takes two functions and
>> composes them and applies the result to a value.
>>
>> So readFirst xs = (readFile.head) xs, or just readFirst = readFile . head.
>> But readFirst xs = (readFile $ head) xs will also fail, because readFile
>> doesn't work on objects of type head.
>>
>> On Fri, Apr 3, 2015 at 9:23 PM, Vale Cofer-Shabica
>> <vale.cofershabica at gmail.com> wrote:
>>>
>>> Could someone please explain why the commented line fails
>>> spectacularly while the final line succeeds?
>>>
>>> >import System.IO (getContents)
>>> >import System.Environment (getArgs)
>>>
>>> >fileInput :: IO String
>>> >fileInput = getArgs>>=readFirst where
>>> >  readFirst :: [FilePath] -> IO String
>>> >  readFirst [] = System.IO.getContents
>>> >--readFirst xs = readFile.head xs
>>> >  readFirst xs = readFile $ head xs
>>>
>>>
>>> I'm particularly confused given the following typings (from ghci):
>>>
>>> readFile.head :: [FilePath] -> IO String
>>> readFile.head [] :: a -> IO String
>>>
>>> And this is still stranger:
>>>
>>> :type readFile.head ["foo", "bar"]
>>>
>>> <interactive>:28:16:
>>>     Couldn't match expected type `a0 -> FilePath'
>>>                 with actual type `[Char]'
>>>     In the expression: "foo"
>>>     In the first argument of `head', namely `["foo", "bar"]'
>>>     In the second argument of `(.)', namely `head ["foo", "bar"]'
>>>
>>> <interactive>:28:23:
>>>     Couldn't match expected type `a0 -> FilePath'
>>>                 with actual type `[Char]'
>>>     In the expression: "bar"
>>>     In the first argument of `head', namely `["foo", "bar"]'
>>>     In the second argument of `(.)', namely `head ["foo", "bar"]'
>>>
>>>
>>> Many thanks in advance,
>>> vale
>>> _______________________________________________
>>> Beginners mailing list
>>> Beginners at haskell.org
>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>
>>
>>
>> On Fri, Apr 3, 2015 at 9:23 PM, Vale Cofer-Shabica
>> <vale.cofershabica at gmail.com> wrote:
>>>
>>> Could someone please explain why the commented line fails
>>> spectacularly while the final line succeeds?
>>>
>>> >import System.IO (getContents)
>>> >import System.Environment (getArgs)
>>>
>>> >fileInput :: IO String
>>> >fileInput = getArgs>>=readFirst where
>>> >  readFirst :: [FilePath] -> IO String
>>> >  readFirst [] = System.IO.getContents
>>> >--readFirst xs = readFile.head xs
>>> >  readFirst xs = readFile $ head xs
>>>
>>>
>>> I'm particularly confused given the following typings (from ghci):
>>>
>>> readFile.head :: [FilePath] -> IO String
>>> readFile.head [] :: a -> IO String
>>>
>>> And this is still stranger:
>>>
>>> :type readFile.head ["foo", "bar"]
>>>
>>> <interactive>:28:16:
>>>     Couldn't match expected type `a0 -> FilePath'
>>>                 with actual type `[Char]'
>>>     In the expression: "foo"
>>>     In the first argument of `head', namely `["foo", "bar"]'
>>>     In the second argument of `(.)', namely `head ["foo", "bar"]'
>>>
>>> <interactive>:28:23:
>>>     Couldn't match expected type `a0 -> FilePath'
>>>                 with actual type `[Char]'
>>>     In the expression: "bar"
>>>     In the first argument of `head', namely `["foo", "bar"]'
>>>     In the second argument of `(.)', namely `head ["foo", "bar"]'
>>>
>>>
>>> Many thanks in advance,
>>> vale
>>> _______________________________________________
>>> Beginners mailing list
>>> Beginners at haskell.org
>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>
>>
>>
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>
>
>
>
> --
> Regards
>
> Sumit Sahrawat


More information about the Beginners mailing list