diff --git a/packages/components/src/components/FunctionChart.tsx b/packages/components/src/components/FunctionChart.tsx
index d774f3db..5a37f0ca 100644
--- a/packages/components/src/components/FunctionChart.tsx
+++ b/packages/components/src/components/FunctionChart.tsx
@@ -7,34 +7,11 @@ import {
   lambdaValue,
   environment,
   runForeign,
-  squiggleExpression,
-  errorValue,
-  errorValueToString,
 } from "@quri/squiggle-lang";
-import { createClassFromSpec } from "react-vega";
-import * as percentilesSpec from "../vega-specs/spec-percentiles.json";
-import { DistributionChart } from "./DistributionChart";
-import { NumberShower } from "./NumberShower";
+import { FunctionChart1Dist } from "./FunctionChart1Dist";
+import { FunctionChart1Number } from "./FunctionChart1Number";
 import { ErrorBox } from "./ErrorBox";
 
-let SquigglePercentilesChart = createClassFromSpec({
-  spec: percentilesSpec as Spec,
-});
-
-const _rangeByCount = (start: number, stop: number, count: number) => {
-  const step = (stop - start) / (count - 1);
-  const items = _.range(start, stop, step);
-  const result = items.concat([stop]);
-  return result;
-};
-
-function unwrap(x: result): a {
-  if (x.tag === "Ok") {
-    return x.value;
-  } else {
-    throw Error("FAILURE TO UNWRAP");
-  }
-}
 export type FunctionChartSettings = {
   start: number;
   stop: number;
@@ -48,167 +25,47 @@ interface FunctionChartProps {
   height: number;
 }
 
-type percentiles = {
-  x: number;
-  p1: number;
-  p5: number;
-  p10: number;
-  p20: number;
-  p30: number;
-  p40: number;
-  p50: number;
-  p60: number;
-  p70: number;
-  p80: number;
-  p90: number;
-  p95: number;
-  p99: number;
-}[];
-
-type errors = _.Dictionary<
-  {
-    x: number;
-    value: string;
-  }[]
->;
-
-type point = { x: number; value: result };
-
-let getPercentiles = ({ chartSettings, fn, environment }) => {
-  let chartPointsToRender = _rangeByCount(
-    chartSettings.start,
-    chartSettings.stop,
-    chartSettings.count
-  );
-
-  let chartPointsData: point[] = chartPointsToRender.map((x) => {
-    let result = runForeign(fn, [x], environment);
-    if (result.tag === "Ok") {
-      if (result.value.tag == "distribution") {
-        return { x, value: { tag: "Ok", value: result.value.value } };
-      } else {
-        return {
-          x,
-          value: {
-            tag: "Error",
-            value:
-              "Cannot currently render functions that don't return distributions",
-          },
-        };
-      }
-    } else {
-      return {
-        x,
-        value: { tag: "Error", value: errorValueToString(result.value) },
-      };
-    }
-  });
-
-  let initialPartition: [
-    { x: number; value: Distribution }[],
-    { x: number; value: string }[]
-  ] = [[], []];
-
-  let [functionImage, errors] = chartPointsData.reduce((acc, current) => {
-    if (current.value.tag === "Ok") {
-      acc[0].push({ x: current.x, value: current.value.value });
-    } else {
-      acc[1].push({ x: current.x, value: current.value.value });
-    }
-    return acc;
-  }, initialPartition);
-
-  let groupedErrors: errors = _.groupBy(errors, (x) => x.value);
-
-  let percentiles: percentiles = functionImage.map(({ x, value }) => {
-    // We convert it to to a pointSet distribution first, so that in case its a sample set
-    // distribution, it doesn't internally convert it to a pointSet distribution for every
-    // single inv() call.
-    let toPointSet: Distribution = unwrap(value.toPointSet());
-    return {
-      x: x,
-      p1: unwrap(toPointSet.inv(0.01)),
-      p5: unwrap(toPointSet.inv(0.05)),
-      p10: unwrap(toPointSet.inv(0.1)),
-      p20: unwrap(toPointSet.inv(0.2)),
-      p30: unwrap(toPointSet.inv(0.3)),
-      p40: unwrap(toPointSet.inv(0.4)),
-      p50: unwrap(toPointSet.inv(0.5)),
-      p60: unwrap(toPointSet.inv(0.6)),
-      p70: unwrap(toPointSet.inv(0.7)),
-      p80: unwrap(toPointSet.inv(0.8)),
-      p90: unwrap(toPointSet.inv(0.9)),
-      p95: unwrap(toPointSet.inv(0.95)),
-      p99: unwrap(toPointSet.inv(0.99)),
-    };
-  });
-
-  return { percentiles, errors: groupedErrors };
-};
-
 export const FunctionChart: React.FC = ({
   fn,
   chartSettings,
   environment,
-  height
+  height,
 }: FunctionChartProps) => {
-  let [mouseOverlay, setMouseOverlay] = React.useState(0);
-  function handleHover(_name: string, value: unknown) {
-    setMouseOverlay(value as number);
-  }
-  function handleOut() {
-    setMouseOverlay(NaN);
-  }
-  const signalListeners = { mousemove: handleHover, mouseout: handleOut };
-  let mouseItem: result = !!mouseOverlay
-    ? runForeign(fn, [mouseOverlay], environment)
-    : {
-        tag: "Error",
-        value: {
-          tag: "REExpectedType",
-          value: "Hover x-coordinate returned NaN. Expected a number.",
-        },
-      };
-  let showChart =
-    mouseItem.tag === "Ok" && mouseItem.value.tag == "distribution" ? (
-      
-    ) : (
-      <>>
-    );
+  let result = runForeign(fn, [chartSettings.start], environment);
+  let resultType = result.tag === "Ok" ? result.value.tag : "Error";
 
-  let getPercentilesMemoized = React.useMemo(
-    () => getPercentiles({ chartSettings, fn, environment }),
-    [environment, fn]
-  );
-
-  return (
-    <>
-      
-      {showChart}
-      {_.entries(getPercentilesMemoized.errors).map(
-        ([errorName, errorPoints]) => (
-          
-            Values:{" "}
-            {errorPoints
-              .map((r, i) => )
-              .reduce((a, b) => (
-                <>
-                  {a}, {b}
-                >
-              ))}
+  let comp = () => {
+    switch (resultType) {
+      case "distribution":
+        return (
+          
+        );
+      case "number":
+        return (
+          
+        );
+      case "Error":
+        return (
+          The function failed to be run
+        );
+      default:
+        return (
+          
+            There is no function visualization for this type of function
           
-        )
-      )}
-    >
-  );
+        );
+    }
+  };
+
+  return comp();
 };
diff --git a/packages/components/src/components/FunctionChart1Dist.tsx b/packages/components/src/components/FunctionChart1Dist.tsx
new file mode 100644
index 00000000..e1d8333c
--- /dev/null
+++ b/packages/components/src/components/FunctionChart1Dist.tsx
@@ -0,0 +1,214 @@
+import * as React from "react";
+import _ from "lodash";
+import type { Spec } from "vega";
+import {
+  Distribution,
+  result,
+  lambdaValue,
+  environment,
+  runForeign,
+  squiggleExpression,
+  errorValue,
+  errorValueToString,
+} from "@quri/squiggle-lang";
+import { createClassFromSpec } from "react-vega";
+import * as percentilesSpec from "../vega-specs/spec-percentiles.json";
+import { DistributionChart } from "./DistributionChart";
+import { NumberShower } from "./NumberShower";
+import { ErrorBox } from "./ErrorBox";
+
+let SquigglePercentilesChart = createClassFromSpec({
+  spec: percentilesSpec as Spec,
+});
+
+const _rangeByCount = (start: number, stop: number, count: number) => {
+  const step = (stop - start) / (count - 1);
+  const items = _.range(start, stop, step);
+  const result = items.concat([stop]);
+  return result;
+};
+
+function unwrap(x: result): a {
+  if (x.tag === "Ok") {
+    return x.value;
+  } else {
+    throw Error("FAILURE TO UNWRAP");
+  }
+}
+export type FunctionChartSettings = {
+  start: number;
+  stop: number;
+  count: number;
+};
+
+interface FunctionChartProps {
+  fn: lambdaValue;
+  chartSettings: FunctionChartSettings;
+  environment: environment;
+  height: number;
+}
+
+type percentiles = {
+  x: number;
+  p1: number;
+  p5: number;
+  p10: number;
+  p20: number;
+  p30: number;
+  p40: number;
+  p50: number;
+  p60: number;
+  p70: number;
+  p80: number;
+  p90: number;
+  p95: number;
+  p99: number;
+}[];
+
+type errors = _.Dictionary<
+  {
+    x: number;
+    value: string;
+  }[]
+>;
+
+type point = { x: number; value: result };
+
+let getPercentiles = ({ chartSettings, fn, environment }) => {
+  let chartPointsToRender = _rangeByCount(
+    chartSettings.start,
+    chartSettings.stop,
+    chartSettings.count
+  );
+
+  let chartPointsData: point[] = chartPointsToRender.map((x) => {
+    let result = runForeign(fn, [x], environment);
+    if (result.tag === "Ok") {
+      if (result.value.tag == "distribution") {
+        return { x, value: { tag: "Ok", value: result.value.value } };
+      } else {
+        return {
+          x,
+          value: {
+            tag: "Error",
+            value:
+              "Cannot currently render functions that don't return distributions",
+          },
+        };
+      }
+    } else {
+      return {
+        x,
+        value: { tag: "Error", value: errorValueToString(result.value) },
+      };
+    }
+  });
+
+  let initialPartition: [
+    { x: number; value: Distribution }[],
+    { x: number; value: string }[]
+  ] = [[], []];
+
+  let [functionImage, errors] = chartPointsData.reduce((acc, current) => {
+    if (current.value.tag === "Ok") {
+      acc[0].push({ x: current.x, value: current.value.value });
+    } else {
+      acc[1].push({ x: current.x, value: current.value.value });
+    }
+    return acc;
+  }, initialPartition);
+
+  let groupedErrors: errors = _.groupBy(errors, (x) => x.value);
+
+  let percentiles: percentiles = functionImage.map(({ x, value }) => {
+    // We convert it to to a pointSet distribution first, so that in case its a sample set
+    // distribution, it doesn't internally convert it to a pointSet distribution for every
+    // single inv() call.
+    let toPointSet: Distribution = unwrap(value.toPointSet());
+    return {
+      x: x,
+      p1: unwrap(toPointSet.inv(0.01)),
+      p5: unwrap(toPointSet.inv(0.05)),
+      p10: unwrap(toPointSet.inv(0.1)),
+      p20: unwrap(toPointSet.inv(0.2)),
+      p30: unwrap(toPointSet.inv(0.3)),
+      p40: unwrap(toPointSet.inv(0.4)),
+      p50: unwrap(toPointSet.inv(0.5)),
+      p60: unwrap(toPointSet.inv(0.6)),
+      p70: unwrap(toPointSet.inv(0.7)),
+      p80: unwrap(toPointSet.inv(0.8)),
+      p90: unwrap(toPointSet.inv(0.9)),
+      p95: unwrap(toPointSet.inv(0.95)),
+      p99: unwrap(toPointSet.inv(0.99)),
+    };
+  });
+
+  return { percentiles, errors: groupedErrors };
+};
+
+export const FunctionChart1Dist: React.FC = ({
+  fn,
+  chartSettings,
+  environment,
+  height
+}: FunctionChartProps) => {
+  let [mouseOverlay, setMouseOverlay] = React.useState(0);
+  function handleHover(_name: string, value: unknown) {
+    setMouseOverlay(value as number);
+  }
+  function handleOut() {
+    setMouseOverlay(NaN);
+  }
+  const signalListeners = { mousemove: handleHover, mouseout: handleOut };
+  let mouseItem: result = !!mouseOverlay
+    ? runForeign(fn, [mouseOverlay], environment)
+    : {
+        tag: "Error",
+        value: {
+          tag: "REExpectedType",
+          value: "Hover x-coordinate returned NaN. Expected a number.",
+        },
+      };
+  let showChart =
+    mouseItem.tag === "Ok" && mouseItem.value.tag == "distribution" ? (
+      
+    ) : (
+      <>>
+    );
+
+  let getPercentilesMemoized = React.useMemo(
+    () => getPercentiles({ chartSettings, fn, environment }),
+    [environment, fn]
+  );
+
+  return (
+    <>
+      
+      {showChart}
+      {_.entries(getPercentilesMemoized.errors).map(
+        ([errorName, errorPoints]) => (
+          
+            Values:{" "}
+            {errorPoints
+              .map((r, i) => )
+              .reduce((a, b) => (
+                <>
+                  {a}, {b}
+                >
+              ))}
+          
+        )
+      )}
+    >
+  );
+};
diff --git a/packages/components/src/components/FunctionChart1Number.tsx b/packages/components/src/components/FunctionChart1Number.tsx
new file mode 100644
index 00000000..fa72bf71
--- /dev/null
+++ b/packages/components/src/components/FunctionChart1Number.tsx
@@ -0,0 +1,145 @@
+import * as React from "react";
+import _ from "lodash";
+import type { Spec } from "vega";
+import {
+  Distribution,
+  result,
+  lambdaValue,
+  environment,
+  runForeign,
+  squiggleExpression,
+  errorValue,
+  errorValueToString,
+} from "@quri/squiggle-lang";
+import { createClassFromSpec } from "react-vega";
+import * as lineChartSpec from "../vega-specs/spec-line-chart.json";
+import { DistributionChart } from "./DistributionChart";
+import { NumberShower } from "./NumberShower";
+import { ErrorBox } from "./ErrorBox";
+
+let SquiggleLineChart = createClassFromSpec({
+  spec: lineChartSpec as Spec,
+});
+
+const _rangeByCount = (start: number, stop: number, count: number) => {
+  const step = (stop - start) / (count - 1);
+  const items = _.range(start, stop, step);
+  const result = items.concat([stop]);
+  return result;
+};
+
+function unwrap(x: result): a {
+  if (x.tag === "Ok") {
+    return x.value;
+  } else {
+    throw Error("FAILURE TO UNWRAP");
+  }
+}
+export type FunctionChartSettings = {
+  start: number;
+  stop: number;
+  count: number;
+};
+
+interface FunctionChartProps {
+  fn: lambdaValue;
+  chartSettings: FunctionChartSettings;
+  environment: environment;
+  height: number;
+}
+
+type point = { x: number; value: result };
+
+let getFunctionImage = ({ chartSettings, fn, environment }) => {
+  let chartPointsToRender = _rangeByCount(
+    chartSettings.start,
+    chartSettings.stop,
+    chartSettings.count
+  );
+
+  let chartPointsData: point[] = chartPointsToRender.map((x) => {
+    let result = runForeign(fn, [x], environment);
+    if (result.tag === "Ok") {
+      if (result.value.tag == "number") {
+        return { x, value: { tag: "Ok", value: result.value.value } };
+      } else {
+        return {
+          x,
+          value: {
+            tag: "Error",
+            value:
+              "Cannot currently render functions that don't return distributions",
+          },
+        };
+      }
+    } else {
+      return {
+        x,
+        value: { tag: "Error", value: errorValueToString(result.value) },
+      };
+    }
+  });
+
+  let initialPartition: [
+    { x: number; value: number }[],
+    { x: number; value: string }[]
+  ] = [[], []];
+
+  let [functionImage, errors] = chartPointsData.reduce((acc, current) => {
+    if (current.value.tag === "Ok") {
+      acc[0].push({ x: current.x, value: current.value.value });
+    } else {
+      acc[1].push({ x: current.x, value: current.value.value });
+    }
+    return acc;
+  }, initialPartition);
+
+  return { errors, functionImage };
+};
+
+export const FunctionChart1Number: React.FC = ({
+  fn,
+  chartSettings,
+  environment,
+  height,
+}: FunctionChartProps) => {
+  let [mouseOverlay, setMouseOverlay] = React.useState(0);
+  function handleHover(_name: string, value: unknown) {
+    setMouseOverlay(value as number);
+  }
+  function handleOut() {
+    setMouseOverlay(NaN);
+  }
+  const signalListeners = { mousemove: handleHover, mouseout: handleOut };
+  let mouseItem: result = !!mouseOverlay
+    ? runForeign(fn, [mouseOverlay], environment)
+    : {
+        tag: "Error",
+        value: {
+          tag: "REExpectedType",
+          value: "Hover x-coordinate returned NaN. Expected a number.",
+        },
+      };
+
+  let getFunctionImageMemoized = React.useMemo(
+    () => getFunctionImage({ chartSettings, fn, environment }),
+    [environment, fn]
+  );
+
+  let data = getFunctionImageMemoized.functionImage.map(({x, value}) => ({x, y:value}))
+  return (
+    <>
+      
+      {getFunctionImageMemoized.errors.map(({ x, value }) => (
+        
+          Error at point ${x}
+        
+      ))}
+    >
+  );
+};
diff --git a/packages/components/src/components/SquigglePlayground.tsx b/packages/components/src/components/SquigglePlayground.tsx
index 1bbd84a2..c28bf11a 100644
--- a/packages/components/src/components/SquigglePlayground.tsx
+++ b/packages/components/src/components/SquigglePlayground.tsx
@@ -72,9 +72,13 @@ const Display = styled.div`
   max-height: ${(props) => props.maxHeight}px;
 `;
 
-const Row = styled.div`
+interface RowProps {
+  readonly leftPercentage: number;
+}
+
+const Row = styled.div`
   display: grid;
-  grid-template-columns: 50% 50%;
+  grid-template-columns: ${(p) => p.leftPercentage}% ${(p) => 100 - p.leftPercentage}%;
 `;
 const Col = styled.div``;
 
@@ -111,6 +115,7 @@ const schema = yup
       .min(10)
       .max(10000),
     chartHeight: yup.number().required().positive().integer().default(350),
+    leftSize: yup.number().required().positive().integer().min(10).max(100).default(50),
     showTypes: yup.boolean(),
     showControls: yup.boolean(),
     showSummary: yup.boolean(),
@@ -152,14 +157,15 @@ let SquigglePlayground: FC = ({
       showTypes: showTypes,
       showControls: showControls,
       showSummary: showSummary,
+      leftSize: 50,
     },
   });
-  const foo = useWatch({
+  const vars = useWatch({
     control,
   });
   let env: environment = {
-    sampleCount: Number(foo.sampleCount),
-    xyPointLength: Number(foo.xyPointLength),
+    sampleCount: Number(vars.sampleCount),
+    xyPointLength: Number(vars.xyPointLength),
   };
   let getChangeJson = (r: string) => {
     setImportString(r);
@@ -169,17 +175,17 @@ let SquigglePlayground: FC = ({
     } catch (e) {
       setImportsAreValid(false);
     }
-    ("");
   };
   return (
     
       
       
       
+      
       
       
       
-      
+      
         
            = ({
               squiggleString={squiggleString}
               environment={env}
               chartSettings={chartSettings}
-              height={foo.chartHeight}
-              showTypes={foo.showTypes}
-              showControls={foo.showControls}
+              height={vars.chartHeight}
+              showTypes={vars.showTypes}
+              showControls={vars.showControls}
               bindings={defaultBindings}
               jsImports={imports}
-              showSummary={foo.showSummary}
+              showSummary={vars.showSummary}
             />
           
         
diff --git a/packages/components/src/vega-specs/spec-line-chart.json b/packages/components/src/vega-specs/spec-line-chart.json
new file mode 100644
index 00000000..117d9543
--- /dev/null
+++ b/packages/components/src/vega-specs/spec-line-chart.json
@@ -0,0 +1,88 @@
+{
+  "$schema": "https://vega.github.io/schema/vega/v5.json",
+  "width": 500,
+  "height": 200,
+  "padding": 5,
+  "data": [
+    {
+      "name": "facet",
+      "values": [],
+      "format": {
+        "type": "json",
+        "parse": {
+          "timestamp": "date"
+        }
+      }
+    }
+  ],
+  "scales": [
+    {
+      "name": "x",
+      "type": "linear",
+      "nice": true,
+      "domain": {
+        "data": "facet",
+        "field": "x"
+      },
+      "range": "width"
+    },
+    {
+      "name": "y",
+      "type": "linear",
+      "range": "height",
+      "nice": true,
+      "zero": true,
+      "domain": {
+        "data": "facet",
+        "field": "y"
+      }
+    }
+  ],
+  "signals": [
+    {
+      "name": "mousemove",
+      "on": [{ "events": "mousemove", "update": "invert('x', x())" }]
+    },
+    {
+      "name": "mouseout",
+      "on": [{ "events": "mouseout", "update": "invert('x', x())" }]
+    }
+  ],
+  "axes": [
+    {
+      "orient": "bottom",
+      "scale": "x",
+      "grid": false,
+      "labelColor": "#727d93",
+      "tickColor": "#fff",
+      "tickOpacity": 0.0,
+      "domainColor": "#727d93",
+      "domainOpacity": 0.1,
+      "tickCount": 5
+    },
+    {
+      "orient": "left",
+      "scale": "y",
+      "grid": false,
+      "labelColor": "#727d93",
+      "tickColor": "#fff",
+      "tickOpacity": 0.0,
+      "domainColor": "#727d93",
+      "domainOpacity": 0.1,
+      "tickCount": 5
+    }
+  ],
+  "marks": [
+    {
+      "type": "line",
+      "from": { "data": "facet" },
+      "encode": {
+        "enter": {
+          "x": { "scale": "x", "field": "x" },
+          "y": { "scale": "y", "field": "y" },
+          "strokeWidth": { "value": 2 }
+        }
+      }
+    }
+  ]
+}
diff --git a/packages/components/tsconfig.json b/packages/components/tsconfig.json
index c8d799d5..38d28704 100644
--- a/packages/components/tsconfig.json
+++ b/packages/components/tsconfig.json
@@ -20,7 +20,8 @@
   },
   "files": [
     "src/vega-specs/spec-distributions.json",
-    "src/vega-specs/spec-percentiles.json"
+    "src/vega-specs/spec-percentiles.json",
+    "src/vega-specs/spec-line-chart.json"
   ],
   "target": "ES6",
   "include": ["src/**/*", "src/*"],