
Hello, I have a piece of code to represents Sentences, Paragraphs and the Content of an article. I added functions to count the words, code below. My questions: 1- Are these functions idiomatic? 2- Is this an efficient way to do the computation? 3- In different languages, I could (and would) give the same name `wordCount` to the three functions, because the type of the input would clarify the usage. But here GHC throws an error. What's the most idiomatic way to do this in Haskell? type Sentence = String type Paragraph = [Sentence] type Content = [Paragraph] sentWordCount :: Sentence -> Int sentWordCount = length . words parWordCount :: Paragraph -> Int parWordCount = foldr ((+) . sentWordCount) 0 contWordCount :: Content -> Int contWordCount = foldr ((+) . parWordCount) 0 I also have two more practical questions on the following two functions: makeSentence :: String -> Sentence makeSentence x = x::Sentence sentCharCount :: Sentence -> Int sentCharCount x = length $ filter (/= ' ') x 4- About `makeSentence` -- does it make sense to write a function like that just to encapsulate the String type? 5- About `sentCharCount` -- I cannot take the argument x off, the compilator complains. What's the reason? Thanks, -P

Hello Pietro, Il 13 dicembre 2020 alle 10:39 Pietro Grandinetti ha scritto:
Hello, I have a piece of code to represents Sentences, Paragraphs and the Content of an article. I added functions to count the words, code below. My questions:
[…]
I also have two more practical questions on the following two functions:
makeSentence :: String -> Sentence makeSentence x = x::Sentence
You can omit the `:: Sentence` part, since it is specified in the signature above. You can omit the whole function itself to be fair, Sentence is a type synonym!
sentCharCount :: Sentence -> Int sentCharCount x = length $ filter (/= ' ') x
You can write this point-free like this sentCharCount :: Sentence -> Int sentCharCount = length . filter (/= ' ') In this example you can regard `$` as «evaluate everything on the right before anything else», so length $ filter (/= ' ') ^^^^^^ ^^^^^^^^^^^^^^^ | | | | | +-- this has type :: [Char] -> [Char] | +-- length does not work on `[Char] -> [Char]` `.` instead is appropriate λ> :t (.) (.) :: (b -> c) -> (a -> b) -> a -> c Does this clear your doubts? —F

Hello Francesco,
Yes, that helped. However, I believe I shouldn't remove the `makeSentence`. A user of the module is not supposed to know what a `Sentence` is, hence I must provide a function such as `makeSentence`. Right now, its implementation is just a type conversion, but may change later.
This would be my logic in different languages; does it make sense in Haskell?
Do you have any feedback on my questions 1,2 and 3?
Thanks,
-P
________________________________
From: Beginners
Hello, I have a piece of code to represents Sentences, Paragraphs and the Content of an article. I added functions to count the words, code below. My questions:
[…]
I also have two more practical questions on the following two functions:
makeSentence :: String -> Sentence makeSentence x = x::Sentence
You can omit the `:: Sentence` part, since it is specified in the signature above. You can omit the whole function itself to be fair, Sentence is a type synonym!
sentCharCount :: Sentence -> Int sentCharCount x = length $ filter (/= ' ') x
You can write this point-free like this sentCharCount :: Sentence -> Int sentCharCount = length . filter (/= ' ') In this example you can regard `$` as «evaluate everything on the right before anything else», so length $ filter (/= ' ') ^^^^^^ ^^^^^^^^^^^^^^^ | | | | | +-- this has type :: [Char] -> [Char] | +-- length does not work on `[Char] -> [Char]` `.` instead is appropriate λ> :t (.) (.) :: (b -> c) -> (a -> b) -> a -> c Does this clear your doubts? —F _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Il 13 dicembre 2020 alle 19:04 Pietro Grandinetti ha scritto:
Yes, that helped. However, I believe I shouldn't remove the `makeSentence`. A user of the module is not supposed to know what a `Sentence` is, hence I must provide a function such as `makeSentence`.
But they will know, a type synonym is just a way to make signatures prettier/more informative, a program like this foo :: String foo = "foo" k = sentCharCount foo will _not_ be refused by the compiler. IF and when — in the future — you decide to use newtype/data then you will get a compiler error (and in turn would need a constructor with signature `:: String -> Sentence`.
Do you have any feedback on my questions 1,2 and 3?
The functions are clearly written, there is some duplication because of the type synonyms (i.e. `parWordCount` and `contWordCount` are the same function). Do not worry about it now and revisit the exercise once you start using `newtype` and `data` + typeclasses —F
participants (2)
-
Francesco Ariis
-
Pietro Grandinetti