[Haskell-beginners] cleanest way to unwrap a list?

Peter Hall peter.hall at memorphic.com
Wed Aug 15 00:59:46 CEST 2012


This is a bit more "functional". The coordinates are the opposite way
around, and it can probably be expressed a bit more concisely, but
I'll leave that to you. This is the basic idea.

-- maps over a list supplying also the 'index'
mapi f = map (uncurry f) . zip [0..]

-- maps over a list supplying also the coordinate pair
mapii f a = mapi f' a
	where f' i x = mapi (curry f $ i) x



m0 = [[1,2,3], [4,5,6], [7,8,9]]

f (1,1) a = a+1
f (0,2) a = a-1
f (_,_) a = a


mapii f m0 -- [[1,2,3],[4,6,6],[6,8,9]]


Peter


On 14 August 2012 22:50, Carlos J. G. Duarte
<carlos.j.g.duarte at gmail.com> wrote:
>
> I know it's doable. I was asking if there's a practical / elegant  way to do
> it.
> I see a lot of Haskell elegance when the matter is defining math formulas,
> running functions over elements, and so on. But it seems most of that
> elegance goes away when the problem derails a bit.
>
> Now for my problem I come up with this:
>
> modify mat x y f =
>   let (lrows, row, rrows) = getpart mat x
>       (lcols, col, rcols) = getpart row y
>   in lrows ++ [lcols ++ [f col] ++ rcols] ++ rrows
>   where
>     getpart xs x = let (ls, r:rs) = splitAt x xs in (ls, r, rs)
>
> m0 = [[1,2,3], [4,5,6], [7,8,9]]
>
> main = do
>   print m0
>   let m1 = modify m0 1 1 succ
>   let m2 = modify m1 2 0 pred
>   print m2
>
> Which is a bit "awkward" considering the ease it is done in other languages.
>
>
> On 08/14/12 19:35, Tim Perry wrote:
>
> There is a way. Please try to figure it out and if you fail post back with
> your code and we can help you from there.
>
>
>
> On Tue, Aug 14, 2012 at 11:05 AM, Carlos J. G. Duarte
> <carlos.j.g.duarte at gmail.com> wrote:
>>
>> Ok, you all have been showing examples of running functions over elements.
>> Add one, append value, and so on.
>> This works well if there's one or more operations to apply indistinctly to
>> a number of elements.
>>
>> Now, what if we just want to make a single operation to a single element?
>> For example, let's say I have this square matrix
>> [[1,2,3],
>>  [4,5,6],
>>  [7,8,9]]
>>
>> how can we increment the value 5 (position 2,2) *and* decrement the value
>> 7 (position 3,1)?
>>
>> This is a made up example of course, I just want to see / learn if there's
>> a way to apply a function to a specific subset of elements.
>>
>>
>> On 08/14/12 00:06, Jack Henahan wrote:
>>>
>>> Equally,
>>>
>>>      let map' = map . map
>>>      map' (+1) . map (++[3]) $ [[1,2],[3,4]]
>>>      -- [[2,3,4],[4,5,4]]
>>>
>>> And you can really keep stacking those up. I think this approach will be
>>> cleaner in the long run.
>>>
>>> For instance, let's start naming our parts.
>>>         let list = [[1,2],[3,4]]
>>>     let map' = map . map
>>>     let addOne = map' (+1)
>>>     let appendThree = map (++[3])
>>>     let reverseInner = map reverse
>>>
>>> So, from here we can do the following:
>>>         list
>>>     -- [[1,2],[3,4]]
>>>
>>>     -- the first example
>>>     addOne list
>>>     -- [[2,3],[4,5]]
>>>         -- now the second example
>>>     addOne . appendThree $ list
>>>     -- [[2,3,4],[4,5,4]]
>>>
>>>     -- now add one to all members of the list, append three to the list,
>>> reverse the inner lists,
>>>     -- then add one to all members of the new list
>>>
>>>     addOne . reverseInner . appendThree . addOne $ list
>>>     -- [[4,4,3],[4,6,5]]
>>>
>>> Now how would you construct that as a list comprehension? With the method
>>> I've proposed, you need
>>> only use map to operate on the nested lists themselves and map' to
>>> operate on the elements of those
>>> lists.
>>>
>>> ====
>>> Jack Henahan
>>> jhenahan at uvm.edu
>>>
>>> On Aug 13, 2012, at 6:41 PM, Christopher Howard
>>> <christopher.howard at frigidcode.com> wrote:
>>>
>>>> On 08/12/2012 09:37 PM, Shakthi Kannan wrote:
>>>>>
>>>>> Hi,
>>>>>
>>>>> --- On Mon, Aug 13, 2012 at 10:51 AM, Christopher Howard
>>>>> <christopher.howard at frigidcode.com> wrote:
>>>>> | Say, for example, I have the list
>>>>> | [[1,2],[3,4]] and want to add 1 to each inner element, resulting in
>>>>> | [[2,3],[4,5]].
>>>>> \--
>>>>>
>>>>> Like this?
>>>>>
>>>>> ghci> let xxs = [[1,2], [3,4]]
>>>>>
>>>>> ghci> [ [ x+1 | x <- xs] | xs <- xxs ]
>>>>> [[2,3],[4,5]]
>>>>>
>>>>> SK
>>>>>
>>>> Thanks everyone for the responses. I found the list comprehension
>>>> approach satisfactory, as it allows me to cleanly modify each layer of
>>>> the nested array as I unwrap it:
>>>>
>>>> code:
>>>> --------
>>>> b = [[ x+1
>>>>     | x <- xs ++ [3] ]
>>>>     | xs <- [[1,2],[3,4]] ]
>>>>
>>>> *Main> b
>>>> [[2,3,4],[4,5,4]]
>>>> --------
>>>>
>>>> The only downside is that I have to write the layers out in reverse of
>>>> the way I would normally think of them, but that isn't too big of a
>>>> challenge.
>>>>
>>>> I'm not sure how that would be done with map in a way that would be neat
>>>> and readable and wouldn't require declaring extra identifiers. I can't
>>>> give a fair evaluation of the Lens approach because I don't understand
>>>> enough of the theory yet.
>>>>
>>>> --
>>>> frigidcode.com
>>>> indicium.us
>>>>
>>>> _______________________________________________
>>>> Beginners mailing list
>>>> Beginners at haskell.org
>>>> http://www.haskell.org/mailman/listinfo/beginners
>>>
>>>
>>> _______________________________________________
>>> Beginners mailing list
>>> Beginners at haskell.org
>>> http://www.haskell.org/mailman/listinfo/beginners
>>>
>>
>>
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://www.haskell.org/mailman/listinfo/beginners
>
>
>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>



More information about the Beginners mailing list