I'm trying to use operations like square on a list of Int and afterwards give the initial value and the result out in a string. For example:
IntListToString square [5,6,7] should result in something like 5=25 6=36 =7=49
My guess is the declaration has to look like this
IntListToString :: (Int -> Int) -> [Int] -> String
Im struggling with the function itself. Do I have to use the map-function and afterwards convert into the right format?
What would your suggestions on solving this be?
Yes, try
showBeforeAfter before after = show before ++ "=" ++ show after
transformBeforeAfter f x = showBeforeAfter x (f x)
mapBeforeAfter f = map (transformBeforeAfter f)
beforeAfter f xs = unwords (mapBeforeAfter f xs)
where beforeAfter is an implementation of your IntListToString. Please note that function names must start with a symbol (excluding a colon) or a lowercase letter.
Related
I'm having a hard time getting Haskell and functional programming together in my head. What I am trying to do is manipulate a string so that I am printing/returning specific characters each time based on a number given. For example:
printing "testing" 2 = "etn"
printing "testing" 3 = "sn"
I've read a lot online, and from what I understand I can achieve this with filtering and cycling, but I cannot get/understand the syntax of this language to get a working program.
I'll try to describe my thought process so you can follow. This function fits the pattern of creating an output list (here a string) from an input seed (here a string) by repeated function application (here dropping some elements). Thus I choose an implementation with Data.List.unfoldr.
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
Okay so, I need to turn the seed b into (Maybe) an output a and the rest of the string. I'll call this subfunction f and pass it into unfoldr.
printing s n = unfoldr f s
where f b = case drop n b of
[] -> Nothing
(x:xs) -> Just (x,xs)
It turns out that attempting to take the head off the front of the list and returning a Maybe is also a common pattern. It's Data.List.uncons, so
printing s n = unfoldr (uncons . drop n) s
Very smooth! So I test it out, and the output is wrong! Your specified output actually eg. for n=2 selects every 2nd character, ie. drops (n-1) characters.
printing s n = unfoldr (uncons . drop (n-1)) s
I test it again and it matches the desired output. Phew!
To demonstrate the Haskell language some alternative solutions to the accepted answer.
Using list comprehension:
printing :: Int -> String -> String
printing j ls = [s | (i, s) <- zip [1 .. ] ls, mod i j == 0]
Using recursion:
printing' :: Int -> String -> String
printing' n ls
| null ls' = []
| otherwise = x : printing' n xs
where
ls' = drop (n - 1) ls
(x : xs) = ls'
In both cases I flipped the arguments so it is easier to do partial application: printing 5 for example is a new function and will give each 5th character when applied to a string.
Note with a minor modification they will work for any list
takeEvery :: Int -> [a] -> [a]
I need to sum the elements from a 2D list of three- tuples of Ints
E.g[(10,50,50),(60,70,90),(100,100,20)],](50,60,100),(60,70,90),(60,40,30)]
and divide it by 3 and then 255.
right now I have this
PatternMatch:: [Char] -> Bool -> (Int, Int, Int)-> Char
PatternMatch _ _[] = []
PatternMatch ((a,b,c):xs) = (((a + b + c) / 3) / 255) : (PatternMatch xs)
But this returns it as an integer, but I need a char. For that I need a helper function, but idk how to go about this. Please help!
Hoogle and google can easily help you with this question. You are just looking for a function of type Int -> String (char would be restricted to only one digit; also watch out for decimal values). You'll find that the well-known function Show does what you need.
Also, dividing by 3 and 255 makes your code look weird, just divide by 765 at once.
Finally, there's no need for pattern matching for a function like this, you can use the higher order function map :: (a -> b) -> [a] -> [b] and either write your own helper function or use a lambda function:
patternMatch :: [(Int,Int,Int)] -> String
patternMatch = concat . map (show . (\(x,y,z) -> (x+y+z) `div` 765))
P.S.: If you are sure you'll only get integers 0..9, then you can use an even simpler list comprehension:
patternMatch tups = [head . show $ (x+y+z) `div` 765 |(x,y,z) <- tups]
I'm following the NLPWP Computational Linguistics site and trying to create a Haskell procedure to find collocations (most common groupings of two words, like "United States" or "to find") in a list of words. I've got the following working code to find bigram frequency:
import Data.Map (Map)
import qualified Data.Map as Map
-- | Function for creating a list of bigrams
-- | e.g. [("Colorless", "green"), ("green", "ideas")]
bigram :: [a] -> [[a]]
bigram [] = []
bigram [_] = []
bigram xs = take 2 xs : bigram (tail xs)
-- | Helper for freqList and freqBigram
countElem base alow = case (Map.lookup alow base) of
Just v -> Map.insert alow (v + 1) base
Nothing -> Map.insert alow 1 base
-- | Maps each word to its frequency.
freqList alow = foldl countElem Map.empty alow
-- | Maps each bigram to its frequency.
freqBigram alow = foldl countElem Map.empty (bigram alow)
I'm trying to write a function that outputs a Map from each bigram to [freq of bigram]/[(freq word 1)*(freq word 2)]. Could you possibly provide advice on how to approach it?
None of the following code is working, but it gives a vague outline for what I was trying to do.
collocations alow =
| let f key = (Map.lookup key freqBi) / ((Map.lookup (first alow) freqs)*(Map.lookup (last alow) freqs))
in Map.mapWithKey f = freqBi
where freqs = (freqList alow)
where freqBi = (freqBigram alow)
I'm very new to Haskell, so let me know if you've got any idea how to fix the collocations procedure. Style tips are also welcome.
Most of your code looks sane, except for the final colloctions function.
I'm not sure why there's a stray pipe in there after the equals sign. You're not trying to write any kind of pattern guard, so I don't think that should be there.
Map.lookup returns a Maybe key, so trying to do division or multiplication isn't going to work. Maybe what you want is some kind of function that takes a key and a map, and returns the associated count or zero if the key doesn't exist?
Other than that, it looks like you're not too far off having this work.
As I read it, your confusion stems from mistaking types, more or less. General advice: Use type signatures on all your top level functions and make sure they are sensible and what you expect of the function (I often do this even before implementing the function).
Let's take a look at your
-- | Function for creating a list of bigrams
-- | e.g. [("Colorless", "green"), ("green", "ideas")]
bigram :: [a] -> [[a]]
If you're giving in a list of Strings, you'll be getting a list of lists of Strings, so your bigram is a list.
You could decide to be more explicit (only allow Strings instead of sometype a - for the beginning at least). So, actually we get a list of Words an make a list of Bigrams from it:
type Word = String
type Bigram = (Word, Word)
bigram :: [Word] -> [Bigram]
For the implementation you can try to use readily available functions from Data.List, for example zipWith and tail.
Now your freqList and freqBigram look like
freqList :: [Word] -> Map Word Int
freqBigram :: [Word] -> Map Bigram Int
With this error messages of the compiler will be clearer to you. To point at it: Take care what you're doing in the lookups for the word frequencies. You're searching for the frequency of word1 and word2, and the bigram is (word1,word2).
Now you should be able to figure the solution out on your own, I guess.
First of all I advise you to have a look at the function
insertWith :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
maybe you'll recognize the pattern if used
f freqs bg = insertWith (+) bg 1 freqs
Next as #MathematicalOrchid already pointed out your solution is not too far from being correct.
lookup :: Ord k => k -> Map k a -> Maybe a
You already took care of that in your countElems function.
what I'd like to note that there is this neat abstraction called Applicative, which works really well for problems like yours.
First of all you have to import Control.Applicative if you're using GHC prior to 7.10 for newer versions it is already at your fingertips.
So what does this abstraction provide, similar to Functor it gives you a way to handle "side effects" in your case the possibility of the failing lookup resulting in Nothing.
We have two operators provided by Applicative: pure and <*>, and in addition as every Applicative is required to be a Functor we also get fmap or <$> which are the latter is just an infix alias for convenience.
So how does this apply to your situation?
<*> :: Applicative f => f (a -> b) -> f a -> f b
<$> :: Functor f => a -> b -> f a -> f b
First of all you see that those two look darn similar but with <*> being slightly less familiar.
Now having a function
f :: Int -> Int
f x = x + 3
and
x1 :: Maybe Int
x1 = Just 4
x2 :: Maybe Int
x2 = Nothing
one couldn't simply just f y because that wouldn't typecheck - but and that is the first idea to keep in mind. Maybe is a Functor (it is also an Applicative - it is even more an M-thing, but let's not go there).
f <$> x1 = Just 7
f <$> x2 = Nothing
so you can imagine the f looking up the value and performing the calculation inside the Just and if there is no value - a.k.a. we have the Nothing situation, we'll do what every lazy student does - be lazy and do nothing ;-).
Now we get to the next part <*>
g1 :: Maybe (Int -> Int)
g1 = Just (x + 3)
g2 :: Maybe (Int -> Int)
g2 = Nothing
Still g1 x1 wouldn't work, but
g1 <*> x1 = Just 7
g1 <*> x2 = Nothing
g2 <*> x1 = Nothing -- remember g2 is Nothing
g2 <*> x2 = Nothing
NEAT! - but still how does this solve your problem?
The 'magic' is using both operators ... for multi-argument functions
h :: Int -> Int -> Int
h x y = x + y + 2
and partial function application, which just means put in one value get back a function that waits for the next value.
GHCi> :type h 1
h 1 :: Int -> Int
Now the strange thing happens we can use with a function like h.
GHCi> :type h1 <$> x1
h1 <$> x1 :: Maybe (Int -> Int)
well that's good because then we can use our <*> with it
y1 :: Maybe Int
y1 = Just 7
h1 <$> x1 <*> y1 = Just (4 + 7 + 2)
= Just 13
and this even works with an arbitrary number of arguments
k :: Int -> Int -> Int -> Int -> Int
k x y z w = ...
k <$> x1 <*> y1 <*> z1 <*> w1 = ...
So design a pure function that works with Int, Float, Double or whatever you like and then use the Functor/Applicative abstraction to make your lookup and frequency calculation work with each other.
I came across this very old sudoku code which seems greek to me coz of mainly this ugly type
type T = (Int,Int) -> [Int]
To understand this function for instance
mark :: ((Int,Int),Int) -> T -> T
mark (p#(i,j),n) s q#(x,y) =
if p==q then [n] else
if x==i || y==j || e x i && e y j then delete n $ s q else s q
where e a b = div (a-1) 3==div (b-1) 3
I can replace the T with the actual type
mark :: ((Int,Int),Int) -> (Int,Int)->[Int] -> (Int,Int)->[Int]
mark (p#(i,j),n) s q#(x,y) =
Now the type arguments don't seem to line up properly. p matches perfectly, but i get confused with "s". If I jump into the call for mark it's like this.....here the list I can easily see it's array of key value pairs with keys like (1,2) etc. These have been filtered for blanks or zeros in sudoku.
input :: String -> (Int,Int) -> [Int]
input s = foldr mark (const [1..9]) $
[(p,n) | (p,n) <- zip idx $ map read $ lines s >>= words, n>0]
The mark function is called with this list and accumulator which is a function (const [1..9]). This doesn't fit the type signature.
mark :: ((Int,Int),Int) -> (Int,Int)->[Int] -> (Int,Int)->[Int]
Problem with the code is that I can't see the actual result of the mark function which I still don't understand. When it's passed to a third function it gets some output. Any explanation on how to understand this sphagetti code?
A value of this type
type T = (Int,Int) -> [Int]
maps the coordinates of any sudoku cell (x,y) :: (Int,Int) into a set of the possible values such cell might have (represented as a list of digits [Int]).
The function const [0..9] maps any cell into the set of all digits. It acts as the initial state for a sudoku solver: at the beginning, assume any cell may have any digit.
I want to get the minimum values from two mappings and subtract one from the other. I'm really new to Haskell and am pretty embarrassed by my attempt but I wanted to give it a go before asking!
calc :: (a -> b) -> [a] -> Float
calc = a - b
where
a = minimum map1
b = minimum map2
map1 f xs = [f x | x <- xs]
map2 f xs = [square x | x <- xs]
square x = x*x
I'm getting so many errors that I feel like I must be doing it completely the wrong way?
The first problem is that map2 just discards the function it's given. map1 is just the standard map function, so you don't need to define it. map2 can be defined properly as:
map2 = map square
The second problem is that you haven't supplied map1 and map2 with any arguments in your definition of calc. Is something like this what you want?
calc :: (a -> b) -> [a] -> Float
calc f xs = a - b
where
a = minimum (map f xs)
b = minimum (map2 xs)
Basically, your problem is that you're declaring parameters but not processing them, or using functions that take parameters without actually specifying them. That doesn't work in any language :)
That's not all, however. Your type for calc is wrong. I suggest you think about why this can't work — in particular, what if I say a is String and b is ()? You can try removing the type signature of calc and entering :t calc into GHCi to find out what the type GHC infers for calc is to get a head-start on correcting it.