New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A mini-DSL for Measures. #61

Merged
merged 4 commits into from Apr 7, 2014

Conversation

Projects
None yet
3 participants
@byorgey
Member

byorgey commented Apr 4, 2014

For an example, try this program:

import           Diagrams.Backend.SVG.CmdLine
import           Diagrams.Core.Types
import           Diagrams.Prelude

main = defaultMain (square 1 # lw (Normalized 0.3 `atLeast` Output 2) # frame 0.5)

Then try choosing various output sizes. The line width scales with the output size, until as the output size gets smaller, at some point the line width hits a minimum width of 2 pixels and doesn't go below that no matter how small the output gets.

@jeffreyrosenbluth

This comment has been minimized.

Show comment
Hide comment
@jeffreyrosenbluth

jeffreyrosenbluth Apr 5, 2014

Member

This looks really cool !!
Should I merge it in?

Member

jeffreyrosenbluth commented Apr 5, 2014

This looks really cool !!
Should I merge it in?

@fryguybob

This comment has been minimized.

Show comment
Hide comment
@fryguybob

fryguybob Apr 5, 2014

Member

I agree this is really nice.

Member

fryguybob commented Apr 5, 2014

I agree this is really nice.

@jeffreyrosenbluth

This comment has been minimized.

Show comment
Hide comment
@jeffreyrosenbluth

jeffreyrosenbluth Apr 6, 2014

Member

One issue, in places like arrows where we have to deal with measures separately we would basically have to rewrite convert :: Measure v -> Measure v perhaps we should make it a top level function and export it?

Member

jeffreyrosenbluth commented Apr 6, 2014

One issue, in places like arrows where we have to deal with measures separately we would basically have to rewrite convert :: Measure v -> Measure v perhaps we should make it a top level function and export it?

@byorgey

This comment has been minimized.

Show comment
Hide comment
@byorgey

byorgey Apr 6, 2014

Member

Ah yes, making convert a top-level function sounds like a good idea, though in that case we should probably give it a more descriptive name.

Member

byorgey commented Apr 6, 2014

Ah yes, making convert a top-level function sounds like a good idea, though in that case we should probably give it a more descriptive name.

@jeffreyrosenbluth

This comment has been minimized.

Show comment
Hide comment
@jeffreyrosenbluth

jeffreyrosenbluth Apr 6, 2014

Member

Any name suggestions?

Member

jeffreyrosenbluth commented Apr 6, 2014

Any name suggestions?

@byorgey

This comment has been minimized.

Show comment
Hide comment
@byorgey

byorgey Apr 6, 2014

Member

Though note that is somewhat orthogonal to this pull request; we already had convert as a local function before.

Member

byorgey commented Apr 6, 2014

Though note that is somewhat orthogonal to this pull request; we already had convert as a local function before.

@jeffreyrosenbluth

This comment has been minimized.

Show comment
Hide comment
@jeffreyrosenbluth

jeffreyrosenbluth Apr 6, 2014

Member

Yes, true - but with only a few cases it didn't seem like a big deal to pattern match in arrows

Member

jeffreyrosenbluth commented Apr 6, 2014

Yes, true - but with only a few cases it didn't seem like a big deal to pattern match in arrows

@byorgey

This comment has been minimized.

Show comment
Hide comment
@byorgey

byorgey Apr 6, 2014

Member

Right, I see. Potential names include measureToOutput, interpretMeasure, runMeasure?

Member

byorgey commented Apr 6, 2014

Right, I see. Potential names include measureToOutput, interpretMeasure, runMeasure?

@jeffreyrosenbluth

This comment has been minimized.

Show comment
Hide comment
@jeffreyrosenbluth

jeffreyrosenbluth Apr 7, 2014

Member

I don't want to mess this up. here is what i have so far, what should change?

toOutput
  :: forall v. (Data v, Data (Scalar v), Num (Scalar v), Ord (Scalar v), Fractional (Scalar v))
  => Scalar v -> Scalar v -> Style v -> Style v
toOutput globalToOutput normToOutput =
  gmapAttrs (convert globalToOutput normToOutput)

-- | Convert an aribrary 'Measure' to 'Output' units.
convert :: forall v. (Data v, Data (Scalar v), Num (Scalar v), Ord (Scalar v), Fractional (Scalar v))
  => Scalar v -> Scalar v -> Measure v -> Measure v
convert g n m =
  case (g, n, m) of
     (_,  _, m@(Output _))    -> m
     (_,  _, (Local s))       -> Output s
     (g', _, (Global s))      -> Output (g' * s)
     (_, n', (Normalized s))  -> Output (n' * s * 0.01)

     (g', n', (MinM m1 m2))    -> outBin min (convert g' n' m1) (convert g' n' m2)
     (g', n', (MaxM m1 m2))    -> outBin max (convert g' n' m1) (convert g' n' m2)
     (_ , _ , (ZeroM))         -> Output 0
     (g', n', (NegateM m))     -> outUn negate (convert g' n' m)
     (g', n', (PlusM m1 m2))   -> outBin (+) (convert g' n' m1) (convert g' n' m2)
     (g', n', (ScaleM s m))    -> outUn (s*) (convert g' n' m)
  where
    outUn  op (Output o1)             = Output (op o1)
    outUn  _  _ = error "outUn: The sky is falling!"
    outBin op (Output o1) (Output o2) = Output (o1 `op` o2)
    outBin _ _ _ = error "outBin: Both skies are falling!"
Member

jeffreyrosenbluth commented Apr 7, 2014

I don't want to mess this up. here is what i have so far, what should change?

toOutput
  :: forall v. (Data v, Data (Scalar v), Num (Scalar v), Ord (Scalar v), Fractional (Scalar v))
  => Scalar v -> Scalar v -> Style v -> Style v
toOutput globalToOutput normToOutput =
  gmapAttrs (convert globalToOutput normToOutput)

-- | Convert an aribrary 'Measure' to 'Output' units.
convert :: forall v. (Data v, Data (Scalar v), Num (Scalar v), Ord (Scalar v), Fractional (Scalar v))
  => Scalar v -> Scalar v -> Measure v -> Measure v
convert g n m =
  case (g, n, m) of
     (_,  _, m@(Output _))    -> m
     (_,  _, (Local s))       -> Output s
     (g', _, (Global s))      -> Output (g' * s)
     (_, n', (Normalized s))  -> Output (n' * s * 0.01)

     (g', n', (MinM m1 m2))    -> outBin min (convert g' n' m1) (convert g' n' m2)
     (g', n', (MaxM m1 m2))    -> outBin max (convert g' n' m1) (convert g' n' m2)
     (_ , _ , (ZeroM))         -> Output 0
     (g', n', (NegateM m))     -> outUn negate (convert g' n' m)
     (g', n', (PlusM m1 m2))   -> outBin (+) (convert g' n' m1) (convert g' n' m2)
     (g', n', (ScaleM s m))    -> outUn (s*) (convert g' n' m)
  where
    outUn  op (Output o1)             = Output (op o1)
    outUn  _  _ = error "outUn: The sky is falling!"
    outBin op (Output o1) (Output o2) = Output (o1 `op` o2)
    outBin _ _ _ = error "outBin: Both skies are falling!"
@byorgey

This comment has been minimized.

Show comment
Hide comment
@byorgey

byorgey Apr 7, 2014

Member

What's the point of the case?

Also, I think (though I am not entirely sure) that we still need a type signature on the call to convert, like (convert globalToOutput normToOutput :: Measure v -> Measure v). Passing globalToOutput and normToOutput is not good enough to fix the type v, since their types are both Scalar v, and type families are not injective (that is, Scalar v1 ~ Scalar v2 does not imply v1 ~ v2).

Member

byorgey commented Apr 7, 2014

What's the point of the case?

Also, I think (though I am not entirely sure) that we still need a type signature on the call to convert, like (convert globalToOutput normToOutput :: Measure v -> Measure v). Passing globalToOutput and normToOutput is not good enough to fix the type v, since their types are both Scalar v, and type families are not injective (that is, Scalar v1 ~ Scalar v2 does not imply v1 ~ v2).

@byorgey

This comment has been minimized.

Show comment
Hide comment
@byorgey

byorgey Apr 7, 2014

Member

Also, minor bikeshedding, perhaps it would be better to rename toOutput as styleToOutput, and then rename convert as toOutput.

Member

byorgey commented Apr 7, 2014

Also, minor bikeshedding, perhaps it would be better to rename toOutput as styleToOutput, and then rename convert as toOutput.

@jeffreyrosenbluth

This comment has been minimized.

Show comment
Hide comment
@jeffreyrosenbluth

jeffreyrosenbluth Apr 7, 2014

Member

The point of the case was so that outUn andoutBin are in scope,
Is there a better way to do this? Is is more idiomatic to make them top
level functions?

You are correct we do need the type signature of the call to convert.
I agree about the names, just thought I would get it to compile first

Member

jeffreyrosenbluth commented Apr 7, 2014

The point of the case was so that outUn andoutBin are in scope,
Is there a better way to do this? Is is more idiomatic to make them top
level functions?

You are correct we do need the type signature of the call to convert.
I agree about the names, just thought I would get it to compile first

jeffreyrosenbluth added a commit that referenced this pull request Apr 7, 2014

@jeffreyrosenbluth jeffreyrosenbluth merged commit cf6f934 into units Apr 7, 2014

1 check passed

continuous-integration/travis-ci The Travis CI build passed
Details

@jeffreyrosenbluth jeffreyrosenbluth deleted the units-dsl branch Apr 7, 2014

@byorgey

This comment has been minimized.

Show comment
Hide comment
@byorgey

byorgey Apr 7, 2014

Member

Ah, I see re: making outUn and outBin in scope. But in any event you only need to case on m; you can simply reuse g and n which are still in scope.

Member

byorgey commented Apr 7, 2014

Ah, I see re: making outUn and outBin in scope. But in any event you only need to case on m; you can simply reuse g and n which are still in scope.

@jeffreyrosenbluth

This comment has been minimized.

Show comment
Hide comment
@jeffreyrosenbluth

jeffreyrosenbluth Apr 7, 2014

Member

Oh yeah thats true. I'll fix it.

Member

jeffreyrosenbluth commented Apr 7, 2014

Oh yeah thats true. I'll fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment