Skip to content
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
Merged

A mini-DSL for Measures. #61

merged 4 commits into from
Apr 7, 2014

Conversation

byorgey
Copy link
Member

@byorgey 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
Copy link
Member

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

@fryguybob
Copy link
Member

I agree this is really nice.

@jeffreyrosenbluth
Copy link
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?

@byorgey
Copy link
Member Author

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
Copy link
Member

Any name suggestions?

@byorgey
Copy link
Member Author

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
Copy link
Member

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

@byorgey
Copy link
Member Author

byorgey commented Apr 6, 2014

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

@jeffreyrosenbluth
Copy link
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!"

@byorgey
Copy link
Member Author

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
Copy link
Member Author

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
Copy link
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

jeffreyrosenbluth added a commit that referenced this pull request Apr 7, 2014
@jeffreyrosenbluth jeffreyrosenbluth merged commit cf6f934 into units Apr 7, 2014
@jeffreyrosenbluth jeffreyrosenbluth deleted the units-dsl branch April 7, 2014 02:41
@byorgey
Copy link
Member Author

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
Copy link
Member

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
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants