What are the best ways to do field-wise datatype operations?












2














Say I have a datatype like:



data CpuStatRow a = CpuStatRow
{ user :: a
, nice :: a
, system :: a
, idle :: a
, ioWait :: a
, irq :: a
, softIrq :: a
, steal :: a
}


which comes from parsing CPU info from /proc/stat of a linux OS, in which every numeric field is an accumulative value since boot time. So if I want to figure out values during certain period, I need to grab before :: CpuStatRow Int and after :: CpuStatRow Int and do the field-wise difference (assuming proper language extensions):



-- let's not worry about distinction between a raw value and a difference for now ...
type Diff = Int
getDiff :: CpuStatRow Int -> CpuStatRow Int -> CpuStatRow Diff
getDiff after before = CpuStatRow {..}
where
diffOn prj = prj after - prj before
user = diffOn user
nice = diffOn nice
... -- basically same for each field


I'm wondering is there something better to do that:




  • generalize to function of other aritieis (e.g. lift a function f :: a -> b -> c -> d to some f' :: F a -> F b -> F c -> F d

  • can easily work on any datatype, as there are many accumulative values in /proc, applying the same method above is not fun. I have Applicative in mind but that doesn't seems to be "deriving-able" by ghc










share|improve this question






















  • wouldn't it make sense modelling the CpuStateRow using Map?
    – ƛƛƛ
    Nov 20 at 18:35










  • @ƛƛƛ but that'll impose an extra lookup overhead that I don't necessarily need - I already know all fields and there's no adding / removing of them.
    – Javran
    Nov 20 at 19:15
















2














Say I have a datatype like:



data CpuStatRow a = CpuStatRow
{ user :: a
, nice :: a
, system :: a
, idle :: a
, ioWait :: a
, irq :: a
, softIrq :: a
, steal :: a
}


which comes from parsing CPU info from /proc/stat of a linux OS, in which every numeric field is an accumulative value since boot time. So if I want to figure out values during certain period, I need to grab before :: CpuStatRow Int and after :: CpuStatRow Int and do the field-wise difference (assuming proper language extensions):



-- let's not worry about distinction between a raw value and a difference for now ...
type Diff = Int
getDiff :: CpuStatRow Int -> CpuStatRow Int -> CpuStatRow Diff
getDiff after before = CpuStatRow {..}
where
diffOn prj = prj after - prj before
user = diffOn user
nice = diffOn nice
... -- basically same for each field


I'm wondering is there something better to do that:




  • generalize to function of other aritieis (e.g. lift a function f :: a -> b -> c -> d to some f' :: F a -> F b -> F c -> F d

  • can easily work on any datatype, as there are many accumulative values in /proc, applying the same method above is not fun. I have Applicative in mind but that doesn't seems to be "deriving-able" by ghc










share|improve this question






















  • wouldn't it make sense modelling the CpuStateRow using Map?
    – ƛƛƛ
    Nov 20 at 18:35










  • @ƛƛƛ but that'll impose an extra lookup overhead that I don't necessarily need - I already know all fields and there's no adding / removing of them.
    – Javran
    Nov 20 at 19:15














2












2








2







Say I have a datatype like:



data CpuStatRow a = CpuStatRow
{ user :: a
, nice :: a
, system :: a
, idle :: a
, ioWait :: a
, irq :: a
, softIrq :: a
, steal :: a
}


which comes from parsing CPU info from /proc/stat of a linux OS, in which every numeric field is an accumulative value since boot time. So if I want to figure out values during certain period, I need to grab before :: CpuStatRow Int and after :: CpuStatRow Int and do the field-wise difference (assuming proper language extensions):



-- let's not worry about distinction between a raw value and a difference for now ...
type Diff = Int
getDiff :: CpuStatRow Int -> CpuStatRow Int -> CpuStatRow Diff
getDiff after before = CpuStatRow {..}
where
diffOn prj = prj after - prj before
user = diffOn user
nice = diffOn nice
... -- basically same for each field


I'm wondering is there something better to do that:




  • generalize to function of other aritieis (e.g. lift a function f :: a -> b -> c -> d to some f' :: F a -> F b -> F c -> F d

  • can easily work on any datatype, as there are many accumulative values in /proc, applying the same method above is not fun. I have Applicative in mind but that doesn't seems to be "deriving-able" by ghc










share|improve this question













Say I have a datatype like:



data CpuStatRow a = CpuStatRow
{ user :: a
, nice :: a
, system :: a
, idle :: a
, ioWait :: a
, irq :: a
, softIrq :: a
, steal :: a
}


which comes from parsing CPU info from /proc/stat of a linux OS, in which every numeric field is an accumulative value since boot time. So if I want to figure out values during certain period, I need to grab before :: CpuStatRow Int and after :: CpuStatRow Int and do the field-wise difference (assuming proper language extensions):



-- let's not worry about distinction between a raw value and a difference for now ...
type Diff = Int
getDiff :: CpuStatRow Int -> CpuStatRow Int -> CpuStatRow Diff
getDiff after before = CpuStatRow {..}
where
diffOn prj = prj after - prj before
user = diffOn user
nice = diffOn nice
... -- basically same for each field


I'm wondering is there something better to do that:




  • generalize to function of other aritieis (e.g. lift a function f :: a -> b -> c -> d to some f' :: F a -> F b -> F c -> F d

  • can easily work on any datatype, as there are many accumulative values in /proc, applying the same method above is not fun. I have Applicative in mind but that doesn't seems to be "deriving-able" by ghc







haskell






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 20 at 18:11









Javran

1,48911433




1,48911433












  • wouldn't it make sense modelling the CpuStateRow using Map?
    – ƛƛƛ
    Nov 20 at 18:35










  • @ƛƛƛ but that'll impose an extra lookup overhead that I don't necessarily need - I already know all fields and there's no adding / removing of them.
    – Javran
    Nov 20 at 19:15


















  • wouldn't it make sense modelling the CpuStateRow using Map?
    – ƛƛƛ
    Nov 20 at 18:35










  • @ƛƛƛ but that'll impose an extra lookup overhead that I don't necessarily need - I already know all fields and there's no adding / removing of them.
    – Javran
    Nov 20 at 19:15
















wouldn't it make sense modelling the CpuStateRow using Map?
– ƛƛƛ
Nov 20 at 18:35




wouldn't it make sense modelling the CpuStateRow using Map?
– ƛƛƛ
Nov 20 at 18:35












@ƛƛƛ but that'll impose an extra lookup overhead that I don't necessarily need - I already know all fields and there's no adding / removing of them.
– Javran
Nov 20 at 19:15




@ƛƛƛ but that'll impose an extra lookup overhead that I don't necessarily need - I already know all fields and there's no adding / removing of them.
– Javran
Nov 20 at 19:15












1 Answer
1






active

oldest

votes


















4














If you want to generalize to functions of any arity and any argument type, I think Applicative is the best you will find. Indeed you won't be able to derive it, but at least you can implement pure and (<*>) once and then reuse it for all of your functions rather than having to do the tedium for each of them. And you can ask GHC to derive the Functor instance for you, if nothing else.



If you want to work with "accumulative values" instead of general functions, you could consider adding a Monoid (or just Semigroup) instance, of the form



instance Semigroup a => Semigroup (CpuStatRow a) where
(CpuStatRow x y z ...) <> (CpuStatRow x' y' z') = CpuStatRow (x <> x') (y <> y') (z <> z') ...


As you can imagine that would get tiring quickly, but fortunately you can implement it in terms of Applicative - we're already saving time!



instance Semigroup a => Semigroup (CpuStatRow a) where
(<>) = liftA2 (<>)

instance Monoid a => Monoid (CpuStatRow a) where
mempty = pure mempty





share|improve this answer





















  • thanks for the answer! perhaps a bit off topic but I'm wondering if I can write Applicative instances with template haskell?
    – Javran
    Nov 20 at 23:46










  • I'm sure it is possible for a type as regular as this, but I don't think enough people are writing a ton of types equivalent to (a,a,a,a,a,a,a,a) that this would be built into any library without having to do some work yourself.
    – amalloy
    Nov 21 at 5:47











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399049%2fwhat-are-the-best-ways-to-do-field-wise-datatype-operations%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









4














If you want to generalize to functions of any arity and any argument type, I think Applicative is the best you will find. Indeed you won't be able to derive it, but at least you can implement pure and (<*>) once and then reuse it for all of your functions rather than having to do the tedium for each of them. And you can ask GHC to derive the Functor instance for you, if nothing else.



If you want to work with "accumulative values" instead of general functions, you could consider adding a Monoid (or just Semigroup) instance, of the form



instance Semigroup a => Semigroup (CpuStatRow a) where
(CpuStatRow x y z ...) <> (CpuStatRow x' y' z') = CpuStatRow (x <> x') (y <> y') (z <> z') ...


As you can imagine that would get tiring quickly, but fortunately you can implement it in terms of Applicative - we're already saving time!



instance Semigroup a => Semigroup (CpuStatRow a) where
(<>) = liftA2 (<>)

instance Monoid a => Monoid (CpuStatRow a) where
mempty = pure mempty





share|improve this answer





















  • thanks for the answer! perhaps a bit off topic but I'm wondering if I can write Applicative instances with template haskell?
    – Javran
    Nov 20 at 23:46










  • I'm sure it is possible for a type as regular as this, but I don't think enough people are writing a ton of types equivalent to (a,a,a,a,a,a,a,a) that this would be built into any library without having to do some work yourself.
    – amalloy
    Nov 21 at 5:47
















4














If you want to generalize to functions of any arity and any argument type, I think Applicative is the best you will find. Indeed you won't be able to derive it, but at least you can implement pure and (<*>) once and then reuse it for all of your functions rather than having to do the tedium for each of them. And you can ask GHC to derive the Functor instance for you, if nothing else.



If you want to work with "accumulative values" instead of general functions, you could consider adding a Monoid (or just Semigroup) instance, of the form



instance Semigroup a => Semigroup (CpuStatRow a) where
(CpuStatRow x y z ...) <> (CpuStatRow x' y' z') = CpuStatRow (x <> x') (y <> y') (z <> z') ...


As you can imagine that would get tiring quickly, but fortunately you can implement it in terms of Applicative - we're already saving time!



instance Semigroup a => Semigroup (CpuStatRow a) where
(<>) = liftA2 (<>)

instance Monoid a => Monoid (CpuStatRow a) where
mempty = pure mempty





share|improve this answer





















  • thanks for the answer! perhaps a bit off topic but I'm wondering if I can write Applicative instances with template haskell?
    – Javran
    Nov 20 at 23:46










  • I'm sure it is possible for a type as regular as this, but I don't think enough people are writing a ton of types equivalent to (a,a,a,a,a,a,a,a) that this would be built into any library without having to do some work yourself.
    – amalloy
    Nov 21 at 5:47














4












4








4






If you want to generalize to functions of any arity and any argument type, I think Applicative is the best you will find. Indeed you won't be able to derive it, but at least you can implement pure and (<*>) once and then reuse it for all of your functions rather than having to do the tedium for each of them. And you can ask GHC to derive the Functor instance for you, if nothing else.



If you want to work with "accumulative values" instead of general functions, you could consider adding a Monoid (or just Semigroup) instance, of the form



instance Semigroup a => Semigroup (CpuStatRow a) where
(CpuStatRow x y z ...) <> (CpuStatRow x' y' z') = CpuStatRow (x <> x') (y <> y') (z <> z') ...


As you can imagine that would get tiring quickly, but fortunately you can implement it in terms of Applicative - we're already saving time!



instance Semigroup a => Semigroup (CpuStatRow a) where
(<>) = liftA2 (<>)

instance Monoid a => Monoid (CpuStatRow a) where
mempty = pure mempty





share|improve this answer












If you want to generalize to functions of any arity and any argument type, I think Applicative is the best you will find. Indeed you won't be able to derive it, but at least you can implement pure and (<*>) once and then reuse it for all of your functions rather than having to do the tedium for each of them. And you can ask GHC to derive the Functor instance for you, if nothing else.



If you want to work with "accumulative values" instead of general functions, you could consider adding a Monoid (or just Semigroup) instance, of the form



instance Semigroup a => Semigroup (CpuStatRow a) where
(CpuStatRow x y z ...) <> (CpuStatRow x' y' z') = CpuStatRow (x <> x') (y <> y') (z <> z') ...


As you can imagine that would get tiring quickly, but fortunately you can implement it in terms of Applicative - we're already saving time!



instance Semigroup a => Semigroup (CpuStatRow a) where
(<>) = liftA2 (<>)

instance Monoid a => Monoid (CpuStatRow a) where
mempty = pure mempty






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 20 at 18:28









amalloy

58.7k5101153




58.7k5101153












  • thanks for the answer! perhaps a bit off topic but I'm wondering if I can write Applicative instances with template haskell?
    – Javran
    Nov 20 at 23:46










  • I'm sure it is possible for a type as regular as this, but I don't think enough people are writing a ton of types equivalent to (a,a,a,a,a,a,a,a) that this would be built into any library without having to do some work yourself.
    – amalloy
    Nov 21 at 5:47


















  • thanks for the answer! perhaps a bit off topic but I'm wondering if I can write Applicative instances with template haskell?
    – Javran
    Nov 20 at 23:46










  • I'm sure it is possible for a type as regular as this, but I don't think enough people are writing a ton of types equivalent to (a,a,a,a,a,a,a,a) that this would be built into any library without having to do some work yourself.
    – amalloy
    Nov 21 at 5:47
















thanks for the answer! perhaps a bit off topic but I'm wondering if I can write Applicative instances with template haskell?
– Javran
Nov 20 at 23:46




thanks for the answer! perhaps a bit off topic but I'm wondering if I can write Applicative instances with template haskell?
– Javran
Nov 20 at 23:46












I'm sure it is possible for a type as regular as this, but I don't think enough people are writing a ton of types equivalent to (a,a,a,a,a,a,a,a) that this would be built into any library without having to do some work yourself.
– amalloy
Nov 21 at 5:47




I'm sure it is possible for a type as regular as this, but I don't think enough people are writing a ton of types equivalent to (a,a,a,a,a,a,a,a) that this would be built into any library without having to do some work yourself.
– amalloy
Nov 21 at 5:47


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399049%2fwhat-are-the-best-ways-to-do-field-wise-datatype-operations%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Wiesbaden

Marschland

Dieringhausen