Haskell - How to iterate over all elements in a record type with the same type purely functional iterators for record types

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

Is there a good way to iterate, fold, or loop over all elements in a record that have the same type? For example, in the following OCaml code

type foo = {
    a : int;
    b : float;
    c : int;
    d : float
}

let foo = {
    a = 1;
    b = 2.0;
    c = 3;
    d = 4.0
}

I d like to iterate over all of the integers or floats separately. I am aware of Fieldslib, but it doesn t seem to do what I d like. For example, with Fieldslib, I can write the code:

open Fieldslib
type bar = {
    w : int;
    x : float;
    y : int;
    z : float
} with fields

let bar = {
    w = 1;
    x = 2.0;
    y = 3;
    z = 4.0
}

let print_int bar x = Printf.printf "%d
" (Fieldslib.Field.get x bar)

let print_float bar x = Printf.printf "%f
" (Fieldslib.Field.get x bar);;

Fields_of_bar.iter ~w:(print_int bar) 
                   ~x:(print_float bar)
                   ~y:(print_int bar)
                   ~z:(print_float bar)

But this forces us to iterate over all elements and not just the ints or floats separately. It also requires the function to be called on each element be specified separately. Really, I d like to just say iterate, map, or fold some function to the structure.

If this is difficult with a heterogeneous record type, would it be any easier with a record type where all elements have a single type? In this case, we could define a lens to project out all of the ints, floats, etc.

In some sense, it feels like I want some sort of purely functional iterator that works with record types and if such a technique exists I m not sure what it s called.


Edit 1

Actually, this may be a lot more straight forward than I thought. Fieldslib gives first class elements already. As long as we make a list of all the ones with the same type, we should be fine. In other words:

open Fieldslib
type bar = {
    w : int;
    x : float;
    y : int;
    z : float
} with fields

let ints=[w;y]
let floats=[x;z]

let bar = {
    w = 1;
    x = 2.0;
    y = 3;
    z = 4.0
};;

let print_ints bar = List.iter (fun l -> Printf.printf "%d
" (l bar)) ints
let print_floats bar = List.iter (fun l -> Printf.printf "%f
" (l bar)) floats

More generally, a list of lenses with the same type should make all of this possible since we can then just apply the map, fold, and iter functions from lists.


Edit 2

In case someone wants to run @j-abrahamson s code, here s some mild modifications, so that it ran on my machine

{-# LANGUAGE RankNTypes #-}

import Control.Applicative
import Control.Monad.Identity

data Foo = Foo {
    a :: Int,
    b :: Float,
    c :: Int,
    d :: Float
} deriving Show

type Traversal s a = forall f . Applicative f => (a -> f a) -> (s -> f s)

intsOfFoo :: Traversal Foo Int
intsOfFoo inj foo = build <$> inj (a foo) <*> inj (c foo) where
  build a c = foo { a = a, c = c }

mapOf :: Traversal s a -> (a -> a) -> (s -> s)
mapOf trav f = runIdentity . trav (Identity . f)

foo0 = Foo { a = 1, b = 1, c = 1, d = 1 }

foo1 = mapOf intsOfFoo (+1) foo0

I m also adding the Haskell flag in case this helps anyone else.

Answers

Actually, this may be a lot more straight forward than I thought. Fieldslib gives first class elements already. As long as we make a list of all the ones with the same type, we should be fine. In other words:

open Fieldslib
type bar = {
    w : int;
    x : float;
    y : int;
    z : float
} with fields

let ints=[w;y]
let floats=[x;z]

let bar = {
    w = 1;
    x = 2.0;
    y = 3;
    z = 4.0
};;

let print_ints bar = List.iter (fun l -> Printf.printf "%d
" (l bar)) ints
let print_floats bar = List.iter (fun l -> Printf.printf "%f
" (l bar)) floats

More generally, a list of lenses with the same type should make all of this possible since we can then just apply the map, fold, and iter functions from lists.

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/28662358/how-to-iterate-over-all-elements-in-a-record-type-with-the-same-type-purely-fun

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils