我需要让每个实例 Sphere获得一个唯一标识符,以便没有两个Spheres 相等。我不会提前知道需要制作多少个球体,因此需要一次制作一个,但仍会增加标识符。
我尝试过的大多数解决方案都有这个问题,我最终得到了一个IO a并需要unsafePerformIO来获得价值。
这段代码很接近,但结果identifier总是一样的:
module Shape ( Sphere (..)
, sphere
, newID
) where
import System.Random
import System.IO.Unsafe (unsafePerformIO)
data Sphere = Sphere { identifier :: Int
} deriving (Show, Eq)
sphere :: Sphere
sphere = Sphere { identifier = newID }
newID :: Int
newID = unsafePerformIO (randomRIO (1, maxBound :: Int))
Run Code Online (Sandbox Code Playgroud)
这也可以工作,并且在 REPL 中工作得很好,但是当我把它放在一个函数中时,它只在第一次返回一个新值,然后返回相同的值。
import Data.Unique
sphere = Sphere { identifier = (hashUnique $ unsafePerformIO newUnique) …Run Code Online (Sandbox Code Playgroud) 我有以下数据结构和功能:
data BTree a = BLeaf | BNode (BTree a) a (BTree a) deriving (Show, Eq)
freshNodesS :: BTree String -> State [String] (BTree String)
freshNodesS BLeaf = return BLeaf
freshNodesS (BNode l m r) = do l' <- freshNodesS l
let m' = getFresh m s
let s' = m : s
r' <- freshNodesS r s'
return (BNode l' m' r')
Run Code Online (Sandbox Code Playgroud)
有一个问题,我实际上想使用freshNodesS l应该给出输出的状态(BTree String, [String]),但是在我不能使用的 do 块中(l', s) <- freshNodesS l,我看到的唯一选择是将所有内容都放在 lambda …
我研究了这个,试图理解几个转换器单子如何相互作用,特别是更好地理解单子lift并与单子堆叠。
对于这里找到的 RWST monad (我认为这是最好的文档),它是一个堆叠的 monad,其中 Reader、Writer、State 都是一个 Monadic 层(并且按照堆叠顺序)。或者说应该如何理解呢?当我查看定义时,runRWST :: r -> s -> m (a, s, w)我将其理解为将读取器环境作为状态环境并将任何单子包装在 的m返回值周围RWS。这也意味着这个monad中只存在两层monad。即外部 monadm和包含多个 monad 的元组。
这反过来也意味着您只能使用lift一次。将读取器或状态单子中的值提升到外部单子中。
从这个意义上说get, 和ask只是应用两个内部单子之一的两个函数。对于最后一点,我仍然不确定我是否理解为什么即使阅读了这篇 stackoverflow 帖子,您仍然需要一个reader和一个state -monad 。我猜读者只对只读有意义,但如果不希望这样,可以在两个单独的状态单子周围使用变压器单子吗?
这些评论让我有理由思考并使以下内容更加明确......以下类型定义的内部单子和外部单子是什么?它本身是RWST一个包裹着(因此是外部单子)Either String(内部单子)的单子吗?
type MyRWST a = RWST
(String -> Either String …Run Code Online (Sandbox Code Playgroud) monads haskell functional-programming state-monad monad-transformers
我最近看过Haskell的Monad - State.我已经能够创建与Monad一起运行的函数,但我正在尝试将行为封装到类中,基本上我正在尝试在Haskell中复制这样的事情:
class A {
public:
int x;
void setX(int newX) {
x = newX;
}
void getX() {
return x;
}
}
Run Code Online (Sandbox Code Playgroud)
如果有人能帮助我,我将非常感激.谢谢!
haskell translate referential-transparency state-monad data-structures
可能重复:
在Haskell中创建唯一标签
我有一个数据类型Person和一些输入数据,我将从中创建人员.
我想让每个人都有自己的ID(假设整数[0 ..]).我可以通过递归来做到这一点,但是因为我在Haskell中这样做,所以我想了解monad.我想,State Monad可能是这项工作的最佳人选.
问题是,我并不是很了解很多东西:当我在monad中时(什么功能可以使用内部),我如何将它们连接在一起,如何使'tick'功能提前等等. .
所以我现在坚持这个:滴答功能可能有效,但我不知道如何使用它; 以及如何相继获得人才建设的价值.
import Control.Monad.State
data Person = Person {
id :: Int,
name :: String
} deriving Show
type MyState = Int
startState = 0
tick :: State MyState Int
tick = do
n <- get
put (n+1)
return n
names = ["Adam","Barney","Charlie"]
-- ??? -> persons = [Person 0 "Adam", Person 1 "Barney", Person 2 "Charlie"]
main = do
print $ evalState tick startState
-- ???
Run Code Online (Sandbox Code Playgroud)
编辑:使用Data.Unique或Data.Unique.Id会更容易吗?如何在我的情况下使用它?
我是Monads和Haskell的新手,并试图了解如何在使用它们时返回值.我的代码如下所示:
foo :: A -> B
foo a = do b <- fooC a (C 0)
-- want to return just (B "b")
fooC :: A -> C -> State MyState B
fooC a c = return (B "b")
Run Code Online (Sandbox Code Playgroud)
我试过用snd (snd b),但显然State MyState B不是一个元组?如何返回所需的值(B "b")?
编辑:考虑到丹尼尔的建议,重写如下:
data MyState = MyState String
data C = C Int
foo :: String -> String
-- want to return just "b"
foo a = evalState (fooC a) …Run Code Online (Sandbox Code Playgroud) 有功能可以做功能arrayToList吗:
import Data.Array.ST
import Control.Monad.ST
genArray :: ST s [Int]
genArray = do
a <- new Array (0, 99) 0 :: ST s (STArray s Int Int)
writeArray a 0 1
{- ... write something to the array ... -}
return arrayToList(a)
Run Code Online (Sandbox Code Playgroud)
如果没有,怎么写一个?
如何改进以下滚动总和实施?
type Buffer = State BufferState (Maybe Double)
type BufferState = ( [Double] , Int, Int )
-- circular buffer
buff :: Double -> Buffer
buff newVal = do
( list, ptr, len) <- get
-- if the list is not full yet just accumulate the new value
if length list < len
then do
put ( newVal : list , ptr, len)
return Nothing
else do
let nptr = (ptr - 1) `mod` len
(as,(v:bs)) = splitAt ptr list …Run Code Online (Sandbox Code Playgroud) 通过Learn You a Haskell阅读,我正在尝试构建一个Stack [Int] Int:
ghci>import Control.Monad.State
ghci> let stack = state ([1,2,3]) (1) :: State [Int] Int
<interactive>:58:20:
Couldn't match expected type `s0 -> (State [Int] Int, s0)'
with actual type `[t0]'
In the first argument of `state', namely `([1, 2, 3])'
In the expression: state ([1, 2, 3]) (1) :: State [Int] Int
In an equation for `stack':
stack = state ([1, 2, 3]) (1) :: State [Int] Int
Run Code Online (Sandbox Code Playgroud)
我该如何创建Stack [Int] Int …
23.8.2在haskell书中练习要求我构建如下状态:
put' :: s -> State s ()
put' s = undefined
-- should act like:
-- Prelude> runState (put "blah") "woot"
-- ((),"blah")
Run Code Online (Sandbox Code Playgroud)
我得到的唯一一个类型的实现是
import Control.Monad.Trans.State -- Not sure this is the right import
put' :: s -> State s ()
put' s = state $ \s -> ((), s)
Run Code Online (Sandbox Code Playgroud)
但这会在参数中返回状态runState,而不是put':
?> runState (put' "blah") "woot"
((),"woot")
Run Code Online (Sandbox Code Playgroud)
我需要修复什么haskell杂技?看不出我怎么能访问"blah".