Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell - have a function return an empty character

I'm trying to create a function that drops every n'th element from a string.

dropEvery :: String -> Int -> String
dropEvery str n = map (\(char, indx) -> if indx `mod` n /= 0 then char else ' ') (zip str [1..])

Right now it simply replaces every n'th element with a space, but what am I supposed to put after the "else" if I want it to return an "empty char". I understand that such a thing doesn't exist in Haskell so the question is - how am I supposed to tell Haskell to not return anything and just move on to the next char?

like image 929
Raul Špilev Avatar asked Apr 11 '16 16:04

Raul Špilev


People also ask

Can a Haskell function return nothing?

No. However, you can have functions that return a trivial value.

How do you make a char empty?

You can use c[i]= '\0' or simply c[i] = (char) 0 . The null/empty char is simply a value of zero, but can also be represented as a character with an escaped zero.

Can you have an empty char?

An empty char value does not belong to any char, so Java gives a compile-time error. To create an empty char, we either can assign it a null value \0 or default Unicode value \u0000 .

How do you write an empty string in Haskell?

A String in Haskell is a list of characters. So to match the empty String you need to match an empty list ( [] ). Your pattern (x:xs) will only match lists or String s with at least one element because it consists of one element ( x ) and the rest ( xs ), which could be empty or non-empty.


2 Answers

You can't do this with just map, by definition it can't change the length of the collection it's applied to. However, you can get this to work without too many changes by switching to concatMap. This function requires the your function that you're mapping return a list, then it concatenates all the results together. All you'd need to do is

dropEvery str n =
    concatMap (\(char, indx) -> if indx `mod` n /= 0 then [char] else []) (zip str [1..])
like image 160
bheklilr Avatar answered Oct 20 '22 16:10

bheklilr


map preserves the structure of the list, while your operations modifies it by removing elements. This means you can't use map, but you can use mapMaybe which allows you to provide a function which returns Nothing for elements you want to remove from the output:

import Data.Maybe (mapMaybe)
dropEvery str n = mapMaybe (\(char, indx) -> if indx `mod` n /= 0 then Just(char) else Nothing) (zip str [1..])
like image 22
Lee Avatar answered Oct 20 '22 14:10

Lee