Skip to content

Commit

Permalink
remove decimal output
Browse files Browse the repository at this point in the history
  • Loading branch information
byorgey committed Dec 25, 2024
1 parent 7696564 commit b79664a
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 120 deletions.
8 changes: 2 additions & 6 deletions docs/introduction/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -188,16 +188,12 @@ approximation. For example,
The result of ``(1+1)/(3+4)`` is simply displayed as the fraction
``2/7``, instead of as a decimal approximation like
``0.2857142857142857``. However, we can still use decimal notation to
write rational numbers:
input rational numbers:

::

Disco> 1.2 + 3.5
4.7

In this case Disco displays the answer in decimal form, since we also
used decimal form in the input; internally, however, ``4.7`` is still
represented as the exact fraction ``47/10``.
47/10

Exercises
---------
Expand Down
12 changes: 4 additions & 8 deletions docs/tutorial/arithmetic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,10 @@ still be entered using decimal notation. Try these expressions as
well:

* ``2.3 + 1.6``
* ``1/5.0``
* ``1/7.0``

Disco automatically picks either fractional or decimal notation for
the output, depending on whether any values with decimal points were
used in the input (for example, compare ``1/5`` and ``1/5.0``, or
``1.0/5``). Note that ``1/7.0`` results in ``0.[142857]``;
can you figure out what the brackets indicate?
* ``0.[3] + 0.[3]``
* ``0.[142857]``

Can you figure out what the brackets indicate?

The standard ``floor`` and ``ceiling`` operations are built-in:

Expand Down
24 changes: 2 additions & 22 deletions src/Disco/AST/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
-- language for Disco.
module Disco.AST.Core (
-- * Core AST
RationalDisplay (..),
ShouldMemo (..),
Core (..),
Op (..),
Expand Down Expand Up @@ -44,33 +43,14 @@ import Disco.Names (QName)
import Disco.Pretty
import Disco.Types

-- | A type of flags specifying whether to display a rational number
-- as a fraction or a decimal.
data RationalDisplay = Fraction | Decimal
deriving (Eq, Show, Generic, Data, Ord, Alpha)

instance Semigroup RationalDisplay where
Decimal <> _ = Decimal
_ <> Decimal = Decimal
_ <> _ = Fraction

-- | The 'Monoid' instance for 'RationalDisplay' corresponds to the
-- idea that the result should be displayed as a decimal if any
-- decimal literals are used in the input; otherwise, the default is
-- to display as a fraction. So the identity element is 'Fraction',
-- and 'Decimal' always wins when combining.
instance Monoid RationalDisplay where
mempty = Fraction
mappend = (P.<>)

data ShouldMemo = Memo | NoMemo deriving (Show, Generic, Data, Alpha)

-- | AST for the desugared, untyped core language.
data Core where
-- | A variable.
CVar :: QName Core -> Core
-- | A rational number.
CNum :: RationalDisplay -> Rational -> Core
CNum :: Rational -> Core
-- | A built-in constant.
CConst :: Op -> Core
-- | An injection into a sum type, i.e. a value together with a tag
Expand Down Expand Up @@ -283,7 +263,7 @@ substsQC xs = transform $ \case
instance Pretty Core where
pretty = \case
CVar qn -> pretty qn
CNum _ r
CNum r
| denominator r == 1 -> text (show (numerator r))
| otherwise -> text (show (numerator r)) <> "/" <> text (show (denominator r))
CApp (CConst op) (CPair c1 c2)
Expand Down
10 changes: 3 additions & 7 deletions src/Disco/Compile.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------

-- |
-- Module : Disco.Compile
-- Copyright : disco team and contributors
Expand Down Expand Up @@ -162,9 +158,9 @@ compileDTerm (DTVar _ x) = return $ CVar (coerce x)
compileDTerm (DTPrim ty x) = compilePrim ty x
compileDTerm DTUnit = return CUnit
compileDTerm (DTBool _ b) = return $ CInj (bool L R b) CUnit
compileDTerm (DTChar c) = return $ CNum Fraction (toInteger (fromEnum c) % 1)
compileDTerm (DTNat _ n) = return $ CNum Fraction (n % 1) -- compileNat ty n
compileDTerm (DTRat r) = return $ CNum Decimal r
compileDTerm (DTChar c) = return $ CNum (toInteger (fromEnum c) % 1)
compileDTerm (DTNat _ n) = return $ CNum (n % 1) -- compileNat ty n
compileDTerm (DTRat r) = return $ CNum r
compileDTerm term@(DTAbs q _ _) = do
(xs, tys, body) <- unbindDeep term
cbody <- compileDTerm body
Expand Down
25 changes: 6 additions & 19 deletions src/Disco/Enumerate.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
{-# LANGUAGE NondecreasingIndentation #-}

-----------------------------------------------------------------------------

-----------------------------------------------------------------------------

-- |
-- Module : Disco.Enumerate
-- Copyright : disco team and contributors
Expand Down Expand Up @@ -63,39 +59,30 @@ enumBool = E.mapE toV fromV $ E.finiteList [L, R]
fromV (VInj i VUnit) = i
fromV _ = error "enumBool.fromV: value isn't a bool"

-- | Unsafely extract the numeric value of a @Value@
-- (assumed to be a VNum).
valToRat :: Value -> Rational
valToRat (VNum _ r) = r
valToRat _ = error "valToRat: value isn't a number"

ratToVal :: Rational -> Value
ratToVal = VNum mempty

-- | Enumerate all values of type @Nat@ (0, 1, 2, ...).
enumN :: ValueEnumeration
enumN = E.mapE (ratToVal . fromInteger) (floor . valToRat) E.nat
enumN = E.mapE (ratv . fromInteger) (floor . vrat) E.nat

-- | Enumerate all values of type @Integer@ (0, 1, -1, 2, -2, ...).
enumZ :: ValueEnumeration
enumZ = E.mapE (ratToVal . fromInteger) (floor . valToRat) E.int
enumZ = E.mapE (ratv . fromInteger) (floor . vrat) E.int

-- | Enumerate all values of type @Fractional@ in the Calkin-Wilf
-- order (1, 1/2, 2, 1/3, 3/2, 2/3, 3, ...).
enumF :: ValueEnumeration
enumF = E.mapE ratToVal valToRat E.cw
enumF = E.mapE ratv vrat E.cw

-- | Enumerate all values of type @Rational@ in the Calkin-Wilf order,
-- with negatives interleaved (0, 1, -1, 1/2, -1/2, 2, -2, ...).
enumQ :: ValueEnumeration
enumQ = E.mapE ratToVal valToRat E.rat
enumQ = E.mapE ratv vrat E.rat

-- | Enumerate all Unicode characters.
enumC :: ValueEnumeration
enumC = E.mapE toV fromV (E.boundedEnum @Char)
where
toV = ratToVal . fromIntegral . fromEnum
fromV = toEnum . floor . valToRat
toV = ratv . fromIntegral . fromEnum
fromV = toEnum . floor . vrat

-- | Enumerate all *finite* sets over a certain element type, given an
-- enumeration of the elements. If we think of each finite set as a
Expand Down
16 changes: 6 additions & 10 deletions src/Disco/Interpret/CESK.hs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ step cesk = case cesk of
(In (CVar x) e k) -> case Ctx.lookup' x e of
Nothing -> return $ Up (UnboundError x) k
Just v -> return $ Out v k
(In (CNum d r) _ k) -> return $ Out (VNum d r) k
(In (CNum r) _ k) -> return $ Out (VNum r) k
(In (CConst OMatchErr) _ k) -> return $ Up NonExhaustive k
(In (CConst OEmptyGraph) _ k) -> return $ Out (VGraph empty) k
(In (CConst op) _ k) -> return $ Out (VConst op) k
Expand Down Expand Up @@ -519,7 +519,7 @@ numOp1 :: (Rational -> Rational) -> Value -> Sem r Value
numOp1 f = numOp1' $ return . ratv . f

numOp1' :: (Rational -> Sem r Value) -> Value -> Sem r Value
numOp1' f (VNum _ m) = f m
numOp1' f (VNum m) = f m
numOp1' _ v = error $ "Impossible! numOp1' on non-VNum " ++ show v

numOp2 :: (Rational -> Rational -> Rational) -> Value -> Sem r Value
Expand All @@ -528,11 +528,7 @@ numOp2 (#) = numOp2' $ \m n -> return (ratv (m # n))
numOp2' :: (Rational -> Rational -> Sem r Value) -> Value -> Sem r Value
numOp2' (#) =
arity2 $ \v1 v2 -> case (v1, v2) of
(VNum d1 n1, VNum d2 n2) -> do
res <- n1 # n2
case res of
VNum _ r -> return $ VNum (d1 <> d2) r
_ -> return res
(VNum n1, VNum n2) -> n1 # n2
(VNum {}, _) -> error $ "Impossible! numOp2' on non-VNum " ++ show v2
_ -> error $ "Impossible! numOp2' on non-VNum " ++ show v1

Expand Down Expand Up @@ -570,7 +566,7 @@ valLt :: Value -> Value -> Bool
valLt v1 v2 = valCmp v1 v2 == LT

valCmp :: Value -> Value -> Ordering
valCmp (VNum _ r1) (VNum _ r2) = compare r1 r2
valCmp (VNum r1) (VNum r2) = compare r1 r2
valCmp (VInj L _) (VInj R _) = LT
valCmp (VInj R _) (VInj L _) = GT
valCmp (VInj L v1) (VInj L v2) = valCmp v1 v2
Expand Down Expand Up @@ -728,8 +724,8 @@ mergeM g = go
mergeCons a m1 m2 zs = do
nm <- evalApp g [VPair (intv m1) (intv m2)]
return $ case nm of
VNum _ 0 -> zs
VNum _ n -> (a, numerator n) : zs
VNum 0 -> zs
VNum n -> (a, numerator n) : zs
v -> error $ "Impossible! merge function in mergeM returned non-VNum " ++ show v

------------------------------------------------------------
Expand Down
27 changes: 9 additions & 18 deletions src/Disco/Value.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}

-----------------------------------------------------------------------------

-----------------------------------------------------------------------------

-- |
-- Module : Disco.Value
-- Copyright : disco team and contributors
Expand Down Expand Up @@ -120,9 +116,8 @@ import System.Random (StdGen)
-- | Different types of values which can result from the evaluation
-- process.
data Value where
-- | A numeric value, which also carries a flag saying how
-- fractional values should be diplayed.
VNum :: RationalDisplay -> Rational -> Value
-- | A numeric value.
VNum :: Rational -> Value
-- | A built-in function constant.
VConst :: Op -> Value
-- | An injection into a sum type.
Expand Down Expand Up @@ -187,7 +182,7 @@ pattern VCons h t = VInj R (VPair h t)
-- only reason for actually doing this would be constructing graphs
-- of graphs or maps of maps, or the like.
data SimpleValue where
SNum :: RationalDisplay -> Rational -> SimpleValue
SNum :: Rational -> SimpleValue
SUnit :: SimpleValue
SInj :: Side -> SimpleValue -> SimpleValue
SPair :: SimpleValue -> SimpleValue -> SimpleValue
Expand All @@ -197,7 +192,7 @@ data SimpleValue where

toSimpleValue :: Value -> SimpleValue
toSimpleValue = \case
VNum d n -> SNum d n
VNum n -> SNum n
VUnit -> SUnit
VInj s v1 -> SInj s (toSimpleValue v1)
VPair v1 v2 -> SPair (toSimpleValue v1) (toSimpleValue v2)
Expand All @@ -206,7 +201,7 @@ toSimpleValue = \case
t -> error $ "A non-simple value was passed as simple: " ++ show t

fromSimpleValue :: SimpleValue -> Value
fromSimpleValue (SNum d n) = VNum d n
fromSimpleValue (SNum n) = VNum n
fromSimpleValue SUnit = VUnit
fromSimpleValue (SInj s v) = VInj s (fromSimpleValue v)
fromSimpleValue (SPair v1 v2) = VPair (fromSimpleValue v1) (fromSimpleValue v2)
Expand All @@ -230,13 +225,11 @@ pattern VFun f = VFun_ (ValFun f)

-- XXX write some comments about partiality

-- | A convenience function for creating a default @VNum@ value with a
-- default (@Fractional@) flag.
ratv :: Rational -> Value
ratv = VNum mempty
ratv = VNum

vrat :: Value -> Rational
vrat (VNum _ r) = r
vrat (VNum r) = r
vrat v = error $ "vrat " ++ show v

-- | A convenience function for creating a default @VNum@ value with a
Expand All @@ -245,7 +238,7 @@ intv :: Integer -> Value
intv = ratv . (% 1)

vint :: Value -> Integer
vint (VNum _ n) = numerator n
vint (VNum n) = numerator n
vint v = error $ "vint " ++ show v

vchar :: Value -> Char
Expand Down Expand Up @@ -523,9 +516,7 @@ prettyValue (ty1 :+: _) (VInj L v) = "left" <> prettyVP ty1 v
prettyValue (_ :+: ty2) (VInj R v) = "right" <> prettyVP ty2 v
prettyValue (_ :+: _) v =
error $ "Non-VInj passed with sum type to prettyValue: " ++ show v
prettyValue _ (VNum d r) = text $ case (d, denominator r == 1) of
(Decimal, False) -> prettyDecimal r
_ -> prettyRational r
prettyValue _ (VNum r) = text $ prettyRational r
prettyValue _ (VGen _) = prettyPlaceholder TyGen
prettyValue ty@(_ :->: _) _ = prettyPlaceholder ty
prettyValue (TySet ty) (VBag xs) = braces $ prettySequence ty "," (map fst xs)
Expand Down
2 changes: 1 addition & 1 deletion test/list-poly/expected
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ T
[2, 3 .. -6] : List(ℤ)
[2, 3 .. 8 / 3] : List(𝔽)
[-2, 3 .. 8 / 3] : List(ℚ)
[1.5]
[3/2]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
58 changes: 29 additions & 29 deletions test/syntax-decimals/expected
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,37 @@
2
2
2
3.[45]
3.46[45]
3.111[3]
3.111[3]
3.[3]
38/11
3811/1100
4667/1500
4667/1500
10/3
3/2
1.5
22.7
3.8[3]
3/2
227/10
23/6
T
0.[142857]
0.[052631578947368421]
0.[032258064516129]
0.[175257731958762886597938144329896907216494845360824742268041237113402061855670103092783505154639]
0.[001]
0.0010090817356205852674066599394550958627648839556004036326942482341069626639757820383451059535822401...
0.0000000000000000000000000000000000000000001145742637671319864267636924948858003603123762210263720996...
0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
-0.1
-1.2
-0.09
1/7
1/19
1/31
17/97
1/999
1/991
1/8727963568087712425891397479476727340041449
1/1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1/10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1/100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-1/10
-6/5
-9/100
0
-0.1
-0.15
-0.0003
-1.0003
-1.1
-0.999
-1.3
-104.55
-1/10
-3/20
-3/10000
-10003/10000
-11/10
-999/1000
-13/10
-2091/20
-104
-1

0 comments on commit b79664a

Please sign in to comment.