使用以下代码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
我做错了什么?
答案 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']