在purescript中使用随机类型检查错误

时间:2018-03-24 09:23:46

标签: purescript

使用以下代码insertRnd正常工作,但我无法使用insertRnd进行编译或其他任何编译:

scramble :: ∀ eff. String -> Eff (random :: RANDOM | eff) String
scramble s = foldl insertRnd (take 1 s) (drop 1 s)

insertRnd :: ∀ eff. String -> String -> Eff (random :: RANDOM | eff) String
insertRnd st ch = do
  n <- randomInt 0 $ length st
  pure $ insertAt n ch st

我收到以下错误消息

Could not match type

Eff
  ( random :: RANDOM
  | t2
  )
  String

with type

String

while checking that type forall eff.
                       String
                       -> String
                          -> Eff
                               ( random :: RANDOM
                               | eff
                               )
                               String
is at least as general as type t0 -> t1 -> t0
while checking that expression insertRnd
has type t0 -> t1 -> t0
in value declaration scramble

where t0 is an unknown type
  t1 is an unknown type
  t2 is an unknown type

我做错了什么?

1 个答案:

答案 0 :(得分:0)

首先,您的insertRnd本身并不为我编译,因为没有函数insertAt :: Int -> String -> String -> String(甚至Int -> Char -> String -> String,请参阅下文) 。 There is such function for arrays and lists and some other stuff,但不是字符串。我将在这里假设您自己编写了这样的函数,它存在于您的代码中。

第二次,即使它确实已编译,也会有fold的错误签名:您正试图折叠String,其中包含{{ 1}} s,这意味着折叠函数的第二个参数必须是Char。所以我在这里假设你的Char实际上有以下签名:

insertRnd

第三次,您实际上insertRnd :: ∀ eff. String -> Char -> Eff (random :: RANDOM | eff) String 超过foldl,因为String没有{{1}的实例}}。要折叠字符串的字符,您需要先将字符串转换为String的数组(或其他容器)。幸运的是,有一个有用的功能 - toCharArray

第四,您声称无法编译&#34;其他任何使用Foldable&#34;可能太宽泛了。这是&#34;其他任何内容的完美编译示例&#34;使用Char

insertRnd

最后,您的insertRnd无法编译的原因是main = launchAff do x <- liftEff $ insertRnd "abcd" 'x' log x 期望纯函数foldl作为第一个参数,但您和#39;给它一个有效的功能foldl。难怪有类型不匹配!

a -> b -> a的有效模拟是foldM。这个函数做了类似的事情,除了它链接monad中的调用而不是纯粹的功能组合。例如:

a -> b -> Eff _ a

将以上所有应用于您的代码,这里是最终版本(假设存在foldl):

foldM insertRnd "a" ['b', 'c', 'd']