Skip to content

surya501/MathProblemApp

Repository files navigation

Learning ReScript + React Native: Interactive Math Problem Solver

Overview

This project serves as a comprehensive learning resource for building type-safe mobile applications using the ReScript + React Native stack. Through building an interactive math problem solver, you'll learn the core concepts, patterns, and best practices of this powerful technology combination.

What You'll Learn:

  • 🎯 ReScript Fundamentals - Type system, pattern matching, and functional programming
  • 📱 React Native Development - Cross-platform mobile app development
  • ⚛️ ReScript-React - Type-safe React components and state management
  • 🧮 Interactive UI Design - Calculator interfaces and user feedback systems
  • 🎨 Styling & Theming - React Native StyleSheet and responsive design
  • 🏗️ Project Architecture - Modular code organization and component patterns

Project Structure & Learning Path

MathProblemApp/
├── package.json                 # Dependencies and scripts
├── rescript.json               # ReScript compiler configuration
├── App.js                      # Expo entry point (minimal JS bridge)
├── app.json                    # Expo configuration
├── assets/                     # App icons and images
├── dev.sh                      # Development helper script
└── src/                        # All ReScript source code
    ├── App.res                 # 🎯 Main app - Learn navigation & state
    ├── types/
    │   └── MathProblem.res     # 🎯 Data modeling - Learn type design
    └── components/
        ├── Calculator.res       # 🎯 Interactive UI - Learn complex components
        └── MathProblemList.res # 🎯 List rendering - Learn array handling

Learning Sequence

  1. Start with types/MathProblem.res - Understand ReScript's type system
  2. Study components/MathProblemList.res - Learn component patterns
  3. Examine components/Calculator.res - Explore state management
  4. Analyze App.res - See how components compose together

Quick Start

Prerequisites

  • Node.js 16+ and npm
  • iOS Simulator (Mac) or Android Studio (for mobile testing)
  • VS Code with ReScript extension (recommended)

Setup & Running

# Install dependencies
npm install

# Start development (compiles ReScript + starts Expo)
npm run web          # Run in browser (best for learning)
npm start           # Full Expo dev server
npm run ios         # iOS simulator
npm run android     # Android emulator

# Development commands
npm run res:build   # Compile ReScript once
npm run res:watch   # Watch mode for development
npm run clean       # Reset build cache

Core Technologies Deep Dive

ReScript Language

📖 ReScript Documentation

ReScript is a strongly-typed functional language that compiles to readable JavaScript. Key learning areas:

Type System

// Variant types for exhaustive pattern matching
type difficulty = Easy | Medium | Hard
type attemptStatus = NotAttempted | Correct | Incorrect

// Record types with optional fields
type mathProblem = {
  id: option<string>,          // option<'a> = Some(value) | None
  question: string,
  answer: float,
  difficulty: difficulty,
  status: attemptStatus,
  attempts: int,
}

Pattern Matching

// Exhaustive matching - compiler ensures all cases handled
let getStatusColor = (status: attemptStatus) => {
  switch status {
  | NotAttempted => "#E3F2FD"  // Light blue
  | Correct => "#E8F5E8"       // Light green  
  | Incorrect => "#FFE8E8"     // Light red
  }
}

Function Syntax

// Labeled arguments for clear APIs
let create = (~question: string, ~answer: float, ~difficulty: difficulty) => {
  // Record creation with type inference
  {
    id: None,
    question: question,
    answer: answer,
    difficulty: difficulty,
    status: NotAttempted,
    attempts: 0,
  }
}

Key Learning Resources:

React Native + Expo

📖 React Native Docs | 📖 Expo Docs

React Native enables cross-platform mobile development. Expo simplifies the development workflow:

Why Expo?

  • No native code setup - Start coding immediately
  • Hot reloading - See changes instantly
  • Web support - Test in browser during development
  • Easy deployment - Build and distribute apps easily

Core Components Used

// All imports are typed and checked
open ReactNative

// Component creation with hooks
@react.component
let make = (~problems: array<mathProblem>) => {
  let (currentProblem, setCurrentProblem) = React.useState(() => None)
  
  // JSX-like syntax with type safety
  <View style={styles["container"]}>
    <Text style={styles["title"]}> 
      {React.string("Math Problems")} 
    </Text>
    <FlatList
      data=problems
      keyExtractor={(item, _) => /* type-safe key extraction */}
      renderItem={({item}) => /* component rendering */}
    />
  </View>
}

Key Learning Areas:

ReScript-React

📖 ReScript-React Docs

Type-safe React bindings for ReScript enable confident component development:

Component Patterns

// Component with labeled props
@react.component
let make = (~problem: mathProblem, ~onComplete: (mathProblem, bool) => unit) => {
  // Local state with type inference
  let (display, setDisplay) = React.useState(() => "0")
  let (attempts, setAttempts) = React.useState(() => 0)
  
  // Event handlers with type safety
  let handleSubmit = () => {
    let userAnswer = Js.Float.fromString(display)
    let correct = Js.Math.abs_float(userAnswer -. problem.answer) < 0.001
    onComplete(problem, correct)
  }
  
  // Conditional rendering
  {showResult ? 
    <ResultView correct={correct} answer={problem.answer} /> :
    <CalculatorKeypad onSubmit={handleSubmit} />
  }
}

Hooks Integration

// useState with proper typing
let (state, setState) = React.useState(() => initialValue)

// useEffect for side effects
React.useEffect0(() => {
  // Setup code
  Some(() => {
    // Cleanup function
  })
})

Key Learning Resources:

ReScript React Native Bindings

📖 rescript-react-native Docs

Type-safe bindings for React Native components:

Styling System

// Type-safe style creation
let styles = StyleSheet.create({
  "container": Style.s({
    flex: 1.,
    backgroundColor: "#f5f5f5",
    padding: 20.->Style.dp,
  }),
  "button": Style.s({
    backgroundColor: "#007AFF",
    borderRadius: 8.,
    padding: 16.->Style.dp,
  }),
})

// Style composition
<View style={Style.array([
  styles["button"],
  isActive ? styles["activeButton"] : Style.empty
])}>

Component Integration

// FlatList with type-safe data
<FlatList
  data=problems                    // array<mathProblem>
  keyExtractor={(item, _) => 
    switch item.id {
    | Some(id) => id
    | None => Js.Float.toString(item.createdAt)
    }
  }
  renderItem={({item}) => 
    <ProblemCard problem=item onSelect=handleSelect />
  }
/>

Educational App Features

Interactive Calculator Interface

  • Number keypad with 0-9, decimal point, and operations
  • Display management with proper input validation
  • Submit/Clear functionality with user feedback
  • Backspace support for input correction

3-Attempt Learning System

  • Progress tracking - Shows "Attempt X of 3"
  • Multiple chances - Encourages learning from mistakes
  • Immediate feedback - Correct/incorrect indication
  • Answer revelation - Shows solution after max attempts

Visual Status Management

  • Color-coded problems:
    • 🔵 Blue: Not attempted yet
    • 🟢 Green: Solved correctly
    • 🔴 Red: Failed after 3 attempts
  • Status indicators - "Tap to solve", "✓ Solved", "✗ Failed"
  • Smooth transitions between states

Sample Problem Set

let sampleProblems = [
  MathProblem.create(~question="What is 2 + 2?", ~answer=4.0, ~difficulty=Easy),
  MathProblem.create(~question="What is 15 × 8?", ~answer=120.0, ~difficulty=Medium),
  MathProblem.create(~question="Solve for x: 3x + 7 = 22", ~answer=5.0, ~difficulty=Medium),
  MathProblem.create(~question="What is the square root of 144?", ~answer=12.0, ~difficulty=Easy),
  MathProblem.create(~question="What is 17² - 13²?", ~answer=120.0, ~difficulty=Hard),
  MathProblem.create(~question="If f(x) = 2x + 3, what is f(5)?", ~answer=13.0, ~difficulty=Medium),
]

State Management Patterns

Local State with React Hooks

// App-level state management
let (problems, setProblems) = React.useState(() => sampleProblemsWithIds)
let (currentProblem, setCurrentProblem) = React.useState(() => None)

// Problem completion handler
let handleProblemComplete = (problem: mathProblem, isCorrect: bool) => {
  setProblems(prevProblems =>
    prevProblems->Js.Array2.map(p =>
      p.id == problem.id
        ? {...p, status: isCorrect ? Correct : Incorrect, attempts: p.attempts + 1}
        : p
    )
  )
}

Component Communication

// Parent-child data flow
<Calculator
  problem={problem}
  onComplete={handleProblemComplete}  // Child to parent communication
  onBack={handleBackToList}
/>

// List item interaction
<MathProblemList
  problems={problems}
  onProblemSelect={handleProblemSelect}  // User interaction callback
/>

Essential Libraries & Tools

ReScript Decco (JSON Handling)

📖 ReScript Decco

While not used in this basic app, ReScript Decco is essential for real-world applications handling JSON data:

// Type-safe JSON serialization/deserialization
@decco
type mathProblem = {
  id: option<string>,
  question: string,
  answer: float,
  difficulty: difficulty,
  status: attemptStatus,
  attempts: int,
}

// Auto-generated encode/decode functions
let json = mathProblem_encode(problem)
let problem = mathProblem_decode(json)

When You'll Need Decco:

  • API communication with servers
  • Local storage persistence
  • Data import/export features
  • Firebase Firestore integration (see Future Enhancements)

Development Tools

VS Code Extensions

  • ReScript - Syntax highlighting, error reporting, auto-completion
  • Expo Tools - Expo project management and debugging
  • React Native Tools - Debugging and development support

Build Tools

// package.json scripts
{
  "res:build": "rescript",           // Compile ReScript to JS
  "res:watch": "rescript -w",        // Watch mode for development  
  "res:clean": "rescript clean",     // Clean compiled files
  "clean": "npm run res:clean && rm -rf node_modules/.cache .expo"
}

Common Patterns & Best Practices

Error Handling

// Using option types for nullable values
switch problem.id {
| Some(id) => useExistingId(id)
| None => generateNewId()
}

// Result types for operations that can fail
type result<'a, 'b> = Ok('a) | Error('b)

let validateAnswer = (input: string): result<float, string> => {
  let num = Js.Float.fromString(input)
  Js.Float.isNaN(num) ? Error("Invalid number") : Ok(num)
}

Component Composition

// Reusable styled components
module StyledButton = {
  @react.component
  let make = (~onPress, ~style=?, ~children) => {
    <TouchableOpacity 
      style={Style.array([
        styles["defaultButton"], 
        style->Belt.Option.getWithDefault(Style.empty)
      ])}
      onPress={onPress}>
      {children}
    </TouchableOpacity>
  }
}

// Usage with type safety
<StyledButton onPress={handleSubmit} style={styles["primaryButton"]}>
  <Text> {React.string("Submit Answer")} </Text>
</StyledButton>

Array Operations

// Functional array transformations
let completedProblems = problems
  ->Js.Array2.filter(p => p.status == Correct)
  ->Js.Array2.map(p => p.question)

// Safe array access
let firstProblem = problems->Belt.Array.get(0)  // option<mathProblem>

Learning Exercises

Beginner Level

  1. Add new sample problems - Practice record creation and array operations
  2. Modify difficulty colors - Learn styling and pattern matching
  3. Adjust attempt limits - Understand component props and state

Intermediate Level

  1. Add problem categories - Extend type definitions and filtering
  2. Implement timer functionality - Practice useEffect and time management
  3. Create hint system - Build progressive disclosure UI patterns

Advanced Level

  1. Add data persistence - Integrate localStorage with ReScript Decco
  2. Implement score calculation - Complex state transformations
  3. Build problem generator - Algorithmic problem creation

Future Enhancements

Firebase Real-time Synchronization

📖 Firebase Docs | 📖 ReScript Firebase

Transform this local app into a collaborative learning platform:

// Firebase Firestore integration with ReScript
module FirebaseService = {
  // Real-time problem synchronization
  let subscribeToProblemUpdates = (callback: array<mathProblem> => unit) => {
    // Subscribe to Firestore collection changes
    // Auto-sync problems across devices
    // Handle offline/online state
  }
  
  // Collaborative features
  let shareProgress = (userId: string, problemId: string, attempts: int) => {
    // Share solving progress with teachers/parents
    // Track learning analytics
    // Enable classroom competitions
  }
}

Firebase Integration Benefits:

  • Real-time sync - Problems update across all devices instantly
  • User authentication - Personal progress tracking
  • Collaborative learning - Share problems between classrooms
  • Analytics - Track learning progress and difficulty areas
  • Offline support - Works without internet, syncs when connected

Implementation Path:

  1. Set up Firebase project and Firestore database
  2. Add Firebase SDK and ReScript bindings
  3. Create service layer for data operations
  4. Implement real-time listeners with ReScript subscriptions
  5. Add user authentication and personal progress tracking
  6. Build teacher dashboard for classroom management

Troubleshooting & Learning Tips

Common ReScript Issues

  • Compilation errors - Read error messages carefully, they're very helpful
  • Type mismatches - Use type annotations to clarify intent
  • Missing record fields - Ensure all required fields are provided
  • Pattern matching - Handle all variant cases for exhaustiveness

React Native Development

  • Hot reloading - Shake device or Cmd+R to reload
  • Metro bundler - Clear cache with npm start -- --clear
  • Simulator issues - Reset simulator if styling looks wrong
  • Web vs mobile - Some features work differently on web

Performance Tips

  • Use FlatList for long lists instead of ScrollView
  • Optimize re-renders with React.memo when needed
  • Minimize state updates - batch updates when possible
  • Profile with Flipper for advanced debugging

Resources & Documentation

Core Documentation

Essential Libraries

Community & Learning

Why This Stack?

For Learning

  • Immediate feedback - Compile-time error checking prevents runtime bugs
  • Clear architecture - Functional programming promotes clean, maintainable code
  • Progressive complexity - Start simple, add features incrementally
  • Industry relevance - Skills transfer to web development and other platforms

For Production

  • Type safety - Catch errors before they reach users
  • Performance - React Native provides near-native performance
  • Cross-platform - Single codebase for iOS, Android, and web
  • Maintainability - ReScript's type system makes refactoring safe and easy
  • Ecosystem - Access to entire npm ecosystem with type safety

Ready to master ReScript + React Native? Start exploring the code and building amazing mobile apps! 🚀📱# Testing pre-commit hook

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published