Haskell编程语言的一些鲜为人知但有用的特性是什么.(我理解语言本身鲜为人知,但与我一起工作.即使是对Haskell中简单事物的解释,比如用一行代码定义Fibonacci序列,也会被我推翻.)
我注意到GHC ScopedTypeVariables能够在函数模式中绑定类型变量,但不能让模式.
作为一个最小的例子,考虑类型
data Foo where Foo :: Typeable a => a -> Foo
Run Code Online (Sandbox Code Playgroud)
如果我想访问Foo中的类型,则以下函数无法编译:
fooType :: Foo -> TypeRep
fooType (Foo x) =
let (_ :: a) = x
in typeRep (Proxy::Proxy a)
Run Code Online (Sandbox Code Playgroud)
但是使用这个技巧将类型变量绑定移动到函数调用,它可以正常工作:
fooType (Foo x) =
let helper (_ :: a) = typeRep (Proxy::Proxy a)
in helper x
Run Code Online (Sandbox Code Playgroud)
由于let绑定实际上是伪装的函数绑定,为什么上面两个代码片段不等同?
(在这个例子中,其他解决方案是创建TypeRepwith typeOf x,或者直接绑定变量,就像x :: a在顶级函数中一样.这些选项都不在我的实际代码中,并且使用它们不回答问题.)
在编写Haskell作为之前接触过Lisp的程序员时,我注意到一些奇怪的事情,我无法理解.
编译好:
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ExistentialQuantification #-}
data Foo = forall a. Show a => Foo { getFoo :: a }
showfoo :: Foo -> String
showfoo Foo{getFoo} = do
show getFoo
Run Code Online (Sandbox Code Playgroud)
但这失败了:
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ExistentialQuantification #-}
data Foo = forall a. Show a => Foo { getFoo :: a }
showfoo :: Foo -> String
showfoo foo = do
let Foo{getFoo} = foo
show getFoo
Run Code Online (Sandbox Code Playgroud)
对我而言,第二个片段失败的原因并不明显.
问题是:
我是否因为haskell不是homoiconic这一事实而错过了某些内容或阻止了这种行为?
我的理由是,鉴于:
Haskell需要将记录模式匹配实现为编译器扩展,因为它可以选择使用语法而不是数据.
函数头或let子句中的匹配是两种特殊情况.
很难理解这些特殊情况,因为它们既不能实现也不能直接用语言本身查找. …