刚才我在 Haskell 中做一些代码高尔夫,我遇到了一个当时对我没有多大意义的错误。决定在 GHCi 中检查一下,现在我真的很困惑。
?> :t replicate <$> readLn
replicate <$> readLn :: IO (a -> [a])
?> f <- replicate <$> readLn
-- I type 4 and press Enter
?> :t f
f :: GHC.Types.Any -> [GHC.Types.Any]
Run Code Online (Sandbox Code Playgroud)
为什么f不是类型a -> [a]?我unsafeCoerce当然可以,但那又长又丑。
我是否可以要求实现接口的类具有某个静态字段或方法,并通过泛型类型参数访问/调用该字段或方法?
我有一个接口,Arithmetical<T>它指定了几个函数,如T plus(T o)和T times(T o).我也有一个Vector<N extends Arithmetical<N>>类,它用于具有类型组件的向量(可变维度)N.然而,当我尝试实现点积时,我遇到了一个问题.
我想实现这个方法N dot(Vector<N> o).对于这一点,我打算开始与任何N的零是通过这两个迭代Vector<N>S' List<N>S,将每一对元素的产品给我的总.有没有一种方法可以指定Arithmetical<T>所有实现类必须有一个静态(最好是最终的)字段,ZERO并且开始dot(Vector<N> o)的主体有一些类似的东西N sum = N.ZERO;?
如果没有,那么这个问题还有什么其他方法呢?我想允许0维向量,所以我不能仅仅通过将向量的第一个组件相乘来开始.有没有办法实例化泛型类型的对象,所以我只能指定一个T zero()方法Arithmetical<T>?
我有理由不使用Java的数字类型 - 我希望有复杂组件的向量.
这是算术:
public interface Arithmetical<T> {
public T plus(T o);
public T minus(T o);
public T negate();
public T times(T o);
public T over(T o);
public T inverse();
// …Run Code Online (Sandbox Code Playgroud) 现在有几次,我发现自己定义了:
(<?>) :: [a] -> [a] -> [a]
[] <?> ys = ys
xs <?> _ = xs
Run Code Online (Sandbox Code Playgroud)
当然,这是一个关联操作,空列表[]既是左标识又是右标识。它的功能类似于 Python 的or.
在我看来,这会是一个很好的(<|>),比原来更好的(++)。选择第一个非空列表感觉更像是我对命名类型类的期望,Alternative而不是连接列表。诚然,它不太合适MonadPlus,但我认为为救赎付出的代价很小。我们已经在标准库中拥有(++)和;(<>)我们是否需要另一个同义词,或者一个新函数(据我所知)会更有帮助吗?
我起初认为这可能是一个很好的Alternative例子,但在相关问题的答案ZipList之后的讨论让我相信了事实并非如此。除了向后兼容性和保持明智之外,当前实例而不是这个新实例还有什么理由呢?MonadPlus
我将如何有效地生成加泰罗尼亚数字的无限列表?我现在拥有的东西运行得相当快,但是在我看来,应该有一个更好的方法。
c 1 = 1
c n = sum (zipWith (*) xs (reverse xs)) : xs
where xs = c (n-1)
catalan = map (head . c) [1..]
Run Code Online (Sandbox Code Playgroud)
我尝试使用fix代替,但是lambda不够懒惰,无法终止计算:
catalan = fix (\xs -> xs ++ [zipWith (*) xs (reverse xs)])
Run Code Online (Sandbox Code Playgroud)
我意识到(++)这不是理想的
是否存在这样的更好方法?可以使该功能足够懒惰吗?我知道第 n 个有一个明确的公式,但我宁愿避免使用它。
今天早些时候我正在写一些 Haskell。想出了一些类似的东西
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Foo a = Foo { ParsecT String () (Writer DefinitelyAMonoid) a }
deriving (Functor, Applicative, Monad, MonadWriter DefinitelyAMonoid)
Run Code Online (Sandbox Code Playgroud)
这没有编译。“没有(MonadWriter DefinitelyAMonoid (ParsecT String () (Writer DefinitelyAMonoid)))从数据类型声明的‘派生’子句引起的实例”,GHC 告诉我。所以我决定看看其他一些 MTL 类是否可行,他们确实做到了。Reader和MonadReader,Writer和MonadWriter。所以我转身被 Discord 用户引导到Hackage,问题很明显:
MonadState s m => MonadState s (ParsecT s' u m)
MonadReader r m => MonadReader r (ParsecT s u m)
MonadError e m => MonadError e (ParsecT s u …Run Code Online (Sandbox Code Playgroud) C和C ++允许我们从中返回退出代码main。为什么Haskell不这样做?在我看来,这很简单;只是要求main :: IO Int而不是IO t。
我意识到以下内容不会像C程序员所期望的那样:
main :: IO Int
main = do
return 1 -- Execution continues, thanks to (>>)
putStrLn "Unreachable?"
return 2 -- Exit code 2?
Run Code Online (Sandbox Code Playgroud)
这种退出代码执行起来可能很棘手,但实际上有多么棘手?对我来说,似乎比必须导入好System.Exit。