nw-ab-critique-dimensi…
Review dimensions for validating agent quality - template compliance, safety, testing, and priority validation
Haskell language-specific patterns, GADTs, type classes, and effect systems
$ npx -y skills add nWave-ai/nWave --skill nw-fp-haskell --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/nw-fp-haskellContext preview
The summary Claude sees to decide when to auto-load this skill.
Haskell language-specific patterns, GADTs, type classes, and effect systems
name: nw-fp-haskell agent: nw-functional-software-crafter description: Haskell language-specific patterns, GADTs, type classes, and effect systems user-invocable: false disable-model-invocation: true
Cross-references: [fp-principles](../nw-fp-principles/SKILL.md) | [fp-domain-modeling](../nw-fp-domain-modeling/SKILL.md) | [property-based-testing](../nw-property-based-testing/SKILL.md)
# Install GHCup (manages GHC, cabal, stack, HLS) curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh # Create project mkdir order-service && cd order-service && cabal init --interactive # Or: stack new order-service simple && stack build && stack test
**Test runner**: `cabal test` or `stack test`. Add `hspec`, `QuickCheck`, `hedgehog` to `build-depends`.
data PaymentMethod = CreditCard CardNumber ExpiryDate | BankTransfer AccountNumber | Cash deriving (Eq, Show)
data Customer = Customer
{ customerId :: CustomerId
, customerName :: CustomerName
, customerEmail :: EmailAddress
} deriving (Eq, Show)
newtype OrderId = OrderId Int deriving (Eq, Ord, Show)
newtype EmailAddress = EmailAddress Text deriving (Eq, Show)`newtype` is erased at compile time -- zero runtime overhead, full type safety.
module Domain.Email (EmailAddress, mkEmailAddress, emailToText) where import Data.Text (Text) import qualified Data.Text as T newtype EmailAddress = EmailAddress Text deriving (Eq, Show) mkEmailAddress :: Text -> Either ValidationError EmailAddress mkEmailAddress raw | "@" `T.isInfixOf` raw = Right (EmailAddress raw) | otherwise = Left (InvalidEmail raw)
Export the type but not the constructor. Only `mkEmailAddress` can create values.
-- (.) composes right-to-left processOrder :: RawOrder -> Either OrderError Confirmation processOrder = confirmOrder . priceOrder . validateOrder
placeOrder :: RawOrder -> Either OrderError Confirmation placeOrder raw = do validated <- validateOrder raw priced <- priceOrder validated confirmOrder priced
mkCustomer :: Text -> Text -> Either ValidationError Customer
mkCustomer rawName rawEmail =
Customer
<$> mkCustomerId 0
<*> mkCustomerName rawName
<*> mkEmailAddress rawEmailimport Data.Validation (Validation, failure, success)
mkCustomerV :: Text -> Text -> Validation [ValidationError] Customer
mkCustomerV rawName rawEmail =
Customer
<$> validateName rawName -- Validation [ValidationError] CustomerName
<*> validateEmail rawEmail -- all errors collected, not short-circuitedUnlike `Either` which stops at first error, `Validation` accumulates all failures via its `Applicative` instance.
Haskell enforces purity at the compiler level. `IO` in return type means side effects.
calculateTotal :: Order -> Money -- Pure: compiler guarantees no side effects calculateTotal order = sumOf (orderLines order) saveOrder :: Order -> IO () -- Impure: IO in the type saveOrder order = writeToDatabase order -- calculateTotal CANNOT call saveOrder -- compiler error
-- Layer 1: Pure domain (no IO, no effects) module Domain.Order (calculateDiscount, validateOrder) where calculateDiscount :: Order -> Discount calculateDiscount order | totalLines order > 10 = Discount 0.1 | otherwise = Discount 0.0 -- Layer 2: Effect interfaces (type classes as ports) class Monad m => OrderRepo m where findOrder :: OrderId -> m (Maybe Order) saveOrder :: Order -> m () -- Layer 3: IO implementations (adapters) instance OrderRepo IO where findOrder orderId = queryDatabase orderId saveOrder order = insertDatabase order
**Effect libraries**: Effectful (recommended starting point, best performance) | mtl (existing codebases) | Polysemy (algebraic effect semantics).
**Frameworks**: QuickCheck (original PBT) | Hedgehog (integrated shrinking) | Hspec (BDD) | tasty (composable test tree). See [property-based-testing](../nw-property-based-testing/SKILL.md) for detailed PBT patterns.
import Test.Hspec
import Test.QuickCheck
spec :: Spec
spec = describe "validateOrder" $ do
it "round-trips through serialization" $
property $ \order ->
deserializeOrder (serializeOrder order) === Right order
it "validated orders always have positive totals" $
property $ \rawOrder ->
case validateOrder rawOrder of
Left _ -> discard
Right valid -> orderTotal valid > Money 0import Data.Text (pack) import Test.QuickCheck genValidEmail :: Gen EmailAddress genValidEmail = do user <- listOf1 (elements ['a'..'z']) domain <- listOf1 (elements ['a'..'z']) pure (EmailAddress (pack (user ++ "@" ++ domain ++ ".com")))
{-# LANGUAGE GADTs, DataKinds #-}
data OrderState = Unvalidated | Validated | Priced
data Order (s :: OrderState) where
UnvalidatedOrder :: RawData -> Order 'Unvalidated
ValidatedOrder :: ValidData -> Order 'Validated
PricedOrderAI agents that guide you from idea to working code, with human judgment at every gate. nWave runs inside Claude Code. It breaks feature delivery into seven waves (discover, diverge, discuss, design, devops, distill, deliver).
Repo: nWave-ai/nWave
Review dimensions for validating agent quality - template compliance, safety, testing, and priority validation
Review dimensions for validating agent quality - template compliance, safety, testing, and priority validation
Review dimensions for acceptance test quality - happy path bias, GWT compliance, business language purity, coverage completeness, walking skeleton…
Detailed 5-phase workflow for creating agents - from requirements analysis through validation and iterative refinement
5-layer testing approach for agent validation including adversarial testing, security validation, and prompt injection resistance
Architectural style selection decision matrices, trade-off analysis, structural enforcement rules, and combination patterns. Load when choosing or evaluating…