소스 정보
- 저장소
- nWave-ai/nWave-experimental
- 최근 소스 활동
- 2026년 8월 17일 09:38
- 감지된 SKILL.md 언어
- 영어
- 스타
- 8
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/nWave-ai/nWave-experimental --skill nw-pbt-haskell명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
SOC 직업 분류 기준
| name | nw-pbt-haskell |
| agent | nw-functional-software-crafter |
| description | Haskell property-based testing with QuickCheck and Hedgehog frameworks |
| user-invocable | false |
| Framework | Shrinking | Stateful | Choose When |
|---|---|---|---|
| QuickCheck | Type-based (manual) | Limited (open-source) | Default for most projects. Universal ecosystem support. |
| Hedgehog | Integrated (automatic) | Yes (parallel too) | Need automatic shrinking composition or parallel stateful testing |
QuickCheck is the original PBT framework (2000). Hedgehog is the modern alternative with better shrinking.
import Test.QuickCheck
prop_reverse_involutory :: [Int] -> Bool
prop_reverse_involutory xs = reverse (reverse xs) == xs
-- Run: quickCheck prop_reverse_involutory
-- Or in test suite: testProperty "reverse" prop_reverse_involutory
arbitrary :: Gen Int -- any Int
arbitrary :: Gen String -- any String
arbitrary :: Gen [Int] -- any list of Ints
arbitrary :: Gen Bool
-- Custom Arbitrary
data Color = Red | Green | Blue deriving (Show, Eq)
instance Arbitrary Color where
arbitrary = elements [Red, Green, Blue]
shrink Red = []
shrink _ = [Red]
choose (0, 100) -- bounded int
elements [1, 2, 3] -- pick from list
oneof [gen1, gen2] -- union
frequency [(80, gen1), (20, gen2)] -- weighted
listOf arbitrary -- list
listOf1 arbitrary -- non-empty list
vectorOf 5 arbitrary -- fixed-length list
-- Map
fmap (* 2) arbitrary -- even integers
-- Bind (dependent generation)
do xs <- listOf1 arbitrary
x <- elements xs
return (xs, x)
-- Sized
sized $ \n -> resize (n `div` 2) arbitrary
instance Arbitrary MyType where
arbitrary = ...
shrink (MyType a b) = [MyType a' b | a' <- shrink a]
++ [MyType a b' | b' <- shrink b]
Not supported in open-source QuickCheck. Use Hedgehog for stateful testing, or commercial Quviq QuickCheck (Erlang).
import Hedgehog
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
prop_reverse :: Property
prop_reverse = property $ do
xs <- forAll $ Gen.list (Range.linear 0 100) Gen.alpha
reverse (reverse xs) === xs
-- Run: check prop_reverse
Gen.int (Range.linear 0 100)
Gen.int (Range.constant 0 100) -- no size scaling
Gen.double (Range.linearFrac 0 1)
Gen.string (Range.linear 0 50) Gen.alpha
Gen.bool
Gen.element [Red, Green, Blue]
-- Collections
Gen.list (Range.linear 0 50) Gen.alpha
Gen.nonEmpty (Range.linear 1 50) Gen.alpha
Gen.set (Range.linear 0 20) Gen.int
-- Map
Gen.int (Range.linear 0 100) <&> (* 2)
-- Filter
Gen.filter (> 0) (Gen.int (Range.linear minBound maxBound))
-- Recursive
Gen.recursive Gen.choice
[ Gen.constant Leaf ]
[ Node <$> genTree <*> Gen.int (Range.linear 0 100) <*> genTree ]
Range.linear 0 100 -- scales with size parameter
Range.constant 0 100 -- fixed bounds, no scaling
Range.linearFrac 0.0 1.0 -- fractional, scales with size
Range.singleton 42 -- always 42
Hedgehog supports sequential and parallel state machine testing.
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
import Hedgehog
import Hedgehog.Internal.State
-- Define state and commands
newtype ModelState (v :: * -> *) = ModelState { items :: Map String Int }
data Put (v :: * -> *) = Put String Int deriving (Show, Eq)
data Get (v :: * -> *) = Get String deriving (Show, Eq)
instance HTraversable Put where
htraverse _ (Put k v) = pure (Put k v)
instance HTraversable Get where
htraverse _ (Get k) = pure (Get k)
cPut :: (MonadGen n, MonadIO m, MonadTest m) => Command n m ModelState
cPut = Command
(\state -> Just $ Put <$> Gen.string (Range.linear 1 10) Gen.alpha
<*> Gen.int (Range.linear 0 100))
(\(Put k v) -> liftIO $ storePut realStore k v)
[ Update $ \(ModelState m) (Put k v) _out -> ModelState (Map.insert k v m)
]
cGet :: (MonadGen n, MonadIO m, MonadTest m) => Command n m ModelState
cGet = Command
(\(ModelState m) -> if Map.null m then Nothing
else Just $ Get <$> Gen.element (Map.keys m))
(\(Get k) -> liftIO $ storeGet realStore k)
[ Ensure $ \(ModelState before) _after (Get k) out ->
out === Map.lookup k before
]
prop_store :: Property
prop_store = property $ do
actions <- forAll $ Gen.sequential (Range.linear 1 50)
(ModelState Map.empty) [cPut, cGet]
executeSequential (ModelState Map.empty) actions
For parallel testing, replace Gen.sequential with Gen.parallel and executeSequential with executeParallel. Checks linearizability of concurrent operations.
-- With HSpec
describe "sort" $ do
it "preserves length" $ property $
\(xs :: [Int]) -> length (sort xs) == length xs
-- With Tasty
testGroup "sort" [ testProperty "length" prop_sortLength ]
-- Cabal/Stack: depends on QuickCheck, hspec-discover or tasty
-- With Tasty
testGroup "sort" [ Hedgehog.testProperty "length" prop_sortLength ]
-- Cabal/Stack: depends on hedgehog, tasty-hedgehog