Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write this as implicit recursion?

Tags:

haskell

I'm trying to write a module that can take a string representation of a simple equation, and evaluate it. As a first step, I need to cut the equation into individual tokens; based on the "rules" of takePiece. I tried writing cutEqu as a fold, but ran into the problem that I'm not really folding over the string; I'm taking different sized pieces until it's exhausted. I could cheat and make it fold over a list of numbers equal to the length of the string, but that seems clumsy.

In most of the guides I've read, they note that explicit recursion is a rare occurrence once you understand implicit recursive patterns (like folds and maps), and this seems like a potentially common scenario, but can't find an appropriate standard function to handle it. How would someone go about writing something simple like cutEqu using implicit recursion? I'm sure I could figure out a simple function to encapsulate the behavior, but it not already existing in the standard library suggests that I may be thinking about the scenario wrong.

import Data.Char

isLit :: String -> Bool
isLit = isDigit . head

takePiece :: String -> (String,String)
takePiece str
    | isLit str = break (not . isDigit) str
    | otherwise = splitAt 1 str

cutEqu :: String -> [String]
cutEqu [] = []
cutEqu xs = let (p,rest) = takePiece xs in
            p : cutEqu rest

Edit: Here's my attempt at writing it implicitly:

consumeWith :: ([a] -> ([b],[a])) -> [a] -> [[b]]
consumeWith _ [] = []
consumeWith f xs = let (t, rest) = f xs in
    t : consumeWith f rest

cutEqu' :: String -> [String]
cutEqu' = consumeWith (takePiece)

But again, I'm concerned that anything like this isn't a standard function. Is there a better way of going about this?

like image 221
Carcigenicate Avatar asked Dec 04 '25 17:12

Carcigenicate


1 Answers

The pattern is called unfoldr which has the type signature:

unfoldr :: (b -> Maybe (a, b)) -> b -> [a]

Your cutEq function can be written in terms of unfoldr like this:

import Data.List

cutEq' str = unfoldr go str
  where go [] = Nothing
        go xs = Just $ takePiece xs
like image 126
ErikR Avatar answered Dec 06 '25 08:12

ErikR



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!