You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何更改基于二维列表的Haskell Store Comonad焦点?生命游戏开发求助

使用Haskell Store Comonad开发生命游戏的问题

嘿,我来帮你搞定这个Store Comonad在生命游戏里的问题,先从你的代码和核心需求入手拆解:

基础类型与初始场定义

我们先把你已有的类型和初始测试场整理出来:

type Cel = ((Float, Float), Bool)
type Field2D = [[Cel]]

-- 测试用的初始二维场
initialField2D :: Field2D
initialField2D = [[((0.0, 0.0), True), ((0.0, 1.0), True)],
                  [((1.0, 0.0), True), ((1.0, 1.0), True)]]

先搞懂Store Comonad的结构

Haskell的Control.Comonad.Store里的Store类型本质是带焦点的环境,它的核心定义是:

data Store s a = Store (s -> a) s
  • 第一个参数(s -> a)是「查询函数」:给定一个状态(这里就是二维坐标),返回对应的值(你的Cel)
  • 第二个参数s是当前的焦点:也就是你当前关注的细胞位置

所以你要定义的initialStore2D,正确的类型应该是Store (Int, Int) Cel——用整数坐标作为状态来定位Field2D里的细胞(毕竟生命游戏的格子都是离散的整数位置,你Cel里的Float可能是用来渲染的,不影响定位逻辑)。

构建initialStore2D

首先我们需要一个从坐标获取对应Cel的函数,先写一个基础版(后续可以优化边界处理):

-- 从Field2D中根据坐标(i,j)获取Cel
lookUp :: Field2D -> (Int, Int) -> Cel
lookUp field (i,j) = field !! i !! j

然后用这个函数和初始焦点(比如(0,0))来构造Store:

import Control.Comonad.Store  -- 记得先导入这个模块

initialStore2D :: Store (Int, Int) Cel
initialStore2D = Store (lookUp initialField2D) (0, 0)

如果要处理边界(比如超出场范围的坐标自动循环,模拟 torus 地图),可以把查询函数改成安全版:

lookUpSafe :: Field2D -> (Int, Int) -> Cel
lookUpSafe field (i,j) = let rows = length field
                             cols = length (head field)
                             -- 取模实现循环边界
                             i' = i `mod` rows
                             j' = j `mod` cols
                         in field !! i' !! j'

-- 用安全查询函数构建的Store
initialStore2DSafe :: Store (Int, Int) Cel
initialStore2DSafe = Store (lookUpSafe initialField2D) (0, 0)

如何切换Store的焦点

Store Comonad提供了现成的函数来操作焦点,最常用的有这几个:

  • seek:切换焦点到指定坐标
    这个函数会返回一个新的Store,焦点变成你指定的位置:
    -- 把焦点切换到(1,1)位置
    focusOn11 :: Store (Int, Int) Cel
    focusOn11 = seek (1,1) initialStore2D
    
  • peek:查看指定坐标的值,不改变当前焦点
    如果只是想看看某个位置的细胞状态,不用切换焦点,可以用这个:
    -- 查看(1,0)位置的Cel,原Store的焦点还是(0,0)
    cellAt10 :: Cel
    cellAt10 = peek (1,0) initialStore2D
    
  • pos:获取当前Store的焦点坐标
    想知道现在焦点在哪?用这个:
    currentPos :: (Int, Int)
    currentPos = pos initialStore2D  -- 返回(0,0)
    

内容的提问来源于stack exchange,提问作者Thobro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:50:20